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.
|