-
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 countDocuments
Collection::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 estimatedDocumentCount
Collection::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 estimatedDocumentCount
Collection::count
for countDocuments
Collection::count
for countDocuments
Collection::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.session
and other connection options incount
call, so that it get the correct result in a transaction.Suggested by @alcaeus #4 (comment)