-
Notifications
You must be signed in to change notification settings - Fork 0
PHPORM-50 PHPORM-65 Remove call to deprecated Collection::count for countDocuments
#18
Conversation
Collection::count for countDocumentsCollection::count for estimatedDocumentCount
|
I updated the PR to use |
For now this works, even though it uses the same logic as |
|
In this test: laravel-mongodb/tests/TransactionTest.php Lines 297 to 303 in 9d9c7c8
The 2nd call to I could have used |
|
After some tests, I found that none of I added a test that checks the behaviour of |
150ba36 to
47e4c40
Compare
Collection::count for estimatedDocumentCountCollection::count for countDocuments and estimatedDocumentCount
tests/TransactionTest.php
Outdated
| $this->assertEquals(1, DB::collection('users')->where('age', 20)->get()->count()); | ||
|
|
||
| if ($transaction) { | ||
| // until transaction is committed, count with filter is incorrect |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should not be the case. Consider:
<?php
require __DIR__ . '/vendor/autoload.php';
$client = new MongoDB\Client('mongodb://localhost:27070/?replicaSet=rs0');
$collection = $client->test->foo;
$collection->drop();
$session = $client->startSession();
echo "Starting transaction\n";
$session->startTransaction();
printf("countDocuments: %d\n", $collection->countDocuments([], ['session' => $session]));
echo "Inserting two documents\n";
$collection->insertOne(['name' => 'klinson', 'age' => 20, 'title' => 'admin'], ['session' => $session]);
$collection->insertOne(['name' => 'bryan', 'age' => 18, 'title' => 'user'], ['session' => $session]);
printf("countDocuments: %d\n", $collection->countDocuments([], ['session' => $session]));
$filter = ['age' => 20];
printf("countDocuments(%s): %d\n", json_encode($filter), $collection->countDocuments($filter, ['session' => $session]));
echo "Committing transaction\n";
$session->commitTransaction();
printf("count: %d\n", $collection->count([], ['session' => $session]));
printf("countDocuments: %d\n", $collection->countDocuments([], ['session' => $session]));
printf("estimatedDocumentCount: %d\n", $collection->estimatedDocumentCount(['session' => $session]));
printf("count(%s): %d\n", json_encode($filter), $collection->count($filter, ['session' => $session]));
printf("countDocuments(%s): %d\n", json_encode($filter), $collection->countDocuments($filter, ['session' => $session]));Output:
Starting transaction
countDocuments: 0
Inserting two documents
countDocuments: 2
countDocuments({"age":20}): 1
Committing transaction
count: 2
countDocuments: 2
estimatedDocumentCount: 2
count({"age":20}): 1
countDocuments({"age":20}): 1
Note that per Transactions: Count Operation, the count command cannot be run within a transaction, so your only option is countDocuments() there.
If countDocuments isn't getting an accurate view of the collection, that suggests the library may not be correctly associating it with the transaction (i.e. session may not be passed).
src/Query/Builder.php
Outdated
| return ['countDocuments' => [$wheres, []]]; | ||
| } | ||
|
|
||
| return ['estimatedDocumentCount' => [[], []]]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
estimatedDocumentCount is syntactic sugar for executing the count command without a filter option. That allows it to return an estimated result by consulting the collection metadata instead of executing a query.
I'd be hesitant to silently opt users into this behavior through the same query builder syntax. Another consideration is that you cannot run count within a transaction at all (see: Transactions: Count Operation).
IMO we should consistently use countDocuments here.
If we want to add support for estimatedDocumentCount we should invent some alternative syntax for that down the line.
This requires more overhead on the server side, but I think it'd ultimately serve users better since the counts will always be accurate and execute both within an without a transaction. I expect some users may also rely on the query builder's count() method for things like pagination (despite all the arguments against limit/skip-based pagination).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your guess is correct, options where not passed to MongoDB\Collection::countDocuments().
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
options where not passed to MongoDB\Collection::countDocuments().
I'm not sure if it's a bug dating back to the original transaction implementation, but that seems like something worth tracking in a separate JIRA ticket for visibility.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The options where already missing here: https://github.com/jenssegers/laravel-mongodb/blob/v3.9.5/src/Query/Builder.php#L287
Tracking in PHPORM-65
https://www.mongodb.com/docs/php-library/current/reference/method/MongoDBCollection-count/ Fix pass options to countDocuments for transaction session
Collection::count for countDocuments and estimatedDocumentCountCollection::count for countDocuments
Collection::count for countDocumentsCollection::count for countDocuments
…ountDocuments (#18) https://www.mongodb.com/docs/php-library/current/reference/method/MongoDBCollection-count/ Fix pass options to countDocuments for transaction session
Fix PHPORM-50 and PHPORM-65
MongoDB\Collection::count()is deprecated, replaced byMongoDB\Collection:: countDocuments()when an accurate result is expected.sessionand other connection options incountcall, so that it get the correct result in a transaction.Suggested by @alcaeus #4 (comment)