Description:
The min() and max() options to the find command now require that a hint be specified. We should update the docs here https://docs.mongodb.com/manual/reference/method/cursor.min/
We may also want to update the docs for the 'min' and 'max' field here:
https://docs.mongodb.com/manual/reference/command/find/
This is a backwards breaking change, since any query such as:
db.c.find().min({x:1}).max({x:3})
|
will now fail with an error that asks for an index hint to be provided, e.g.
db.c.find().min({x:1}).max({x:3}).hint({x:1})
|
If drivers have helpers for min() and max(), they may need to be changed.
Please slack or email (or comment on the ticket) if you have any questions!
Engineering Ticket Description:
Issue
Query with min/max modifier uses first index with related fields.
On fresh MongoDB secondary startup `id` index became last in order (this looks like a bug) and `find` operation with `min`/`max` modifier starts using first hashed index by `_id`.
When this secondary became primary, this shard returns incomplete results on query.
user:PRIMARY> db.socialTopics.getIndices()
|
[
|
{
|
"v" : 2,
|
"key" : {
|
"_id" : "hashed"
|
},
|
"name" : "_id_hashed",
|
"background" : true,
|
"ns" : "user.socialTopics"
|
},
|
{
|
"v" : 2,
|
"key" : {
|
"_id" : 1
|
},
|
"name" : "_id_",
|
"ns" : "user.socialTopics"
|
}
|
]
|
user:PRIMARY> db.socialTopics.find({}, {_id: 1}).min({_id: ObjectId("5bb74d8cefa37173fe2cf692")}).sort({_id: 1}).limit(5).explain()
|
{
|
"queryPlanner" : {
|
"plannerVersion" : 1,
|
"namespace" : "user.socialTopics",
|
"indexFilterSet" : false,
|
"parsedQuery" : {
|
|
},
|
"winningPlan" : {
|
"stage" : "PROJECTION",
|
"transformBy" : {
|
"_id" : 1
|
},
|
"inputStage" : {
|
"stage" : "SORT",
|
"sortPattern" : {
|
"_id" : 1
|
},
|
"limitAmount" : 5,
|
"inputStage" : {
|
"stage" : "SORT_KEY_GENERATOR",
|
"inputStage" : {
|
"stage" : "FETCH",
|
"inputStage" : {
|
"stage" : "IXSCAN",
|
"keyPattern" : {
|
"_id" : "hashed"
|
},
|
"indexName" : "_id_hashed",
|
"isMultiKey" : false,
|
"isUnique" : false,
|
"isSparse" : false,
|
"isPartial" : false,
|
"indexVersion" : 2,
|
"direction" : "forward",
|
"indexBounds" : {
|
|
}
|
}
|
}
|
}
|
}
|
},
|
"rejectedPlans" : [ ]
|
},
|
...
|
}
|
Why we use min/max modifier
We use min/max modifier for iterating over collections, because MongoDB don't have operation like `after` or `before`.
We can't use `$gt`/`$gte`/`$lt`/`$lte` because:
- this operations always false for values with differ types;
- it's not trivial to make query with multiple field bounds.
Workaround
Looks like with `hint` we can set correct index directly.