Today I have noticed that the order in which the $lt and $gt operators are given seem to matter in MongoDB 2.0.2.
I have a database of games. “player” is an array of two strings representing both players, “endedAtMS” is a timestamp when the game has ended. I have created this index:
db.games.ensureIndex({player:1,endedAtMS:-1})
To get 30 of my games which were finished in a certain time range, ordered by the time the games where finished, I do:
db.games.find({ "player" : "Stefan" ,
"endedAtMS" : { "$lt" : 1321284969946 ,
"$gt" : 1301284969946}}).
sort({endedAtMS:-1}).
limit(30).
explain()
{
"cursor" : "BtreeCursor player_1_endedAtMS_-1",
"nscanned" : 30,
"nscannedObjects" : 30,
"n" : 30,
"millis" : 0,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : true,
"indexOnly" : false,
"indexBounds" : {
"player" : [
[
"Stefan",
"Stefan"
]
],
"endedAtMS" : [
[
1321284969946,
-1.7976931348623157e+308
]
]
}
}
All seems to work fine. However when I change the order of $lt and $gt in the query above I get this:
db.games.find({ "player" : "Stefan" ,
"endedAtMS" : { "$gt":1301284969946,
"$lt" : 1321284969946}}).
sort({endedAtMS:-1}).
limit(30).
explain()
{
"cursor" : "BtreeCursor player_1_endedAtMS_-1",
"nscanned" : 126,
"nscannedObjects" : 126,
"n" : 30,
"millis" : 1,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : true,
"indexOnly" : false,
"indexBounds" : {
"player" : [
[
"Stefan",
"Stefan"
]
],
"endedAtMS" : [
[
1.7976931348623157e+308,
1301284969946
]
]
}
}
As you can see 126 docs need to be scanned to get the 30 docs for the result. If you take a look at the indexBounds in the explain output it seems that only the first operator is used to limit the search space in the index.
What do I miss? Why is Mongo only using one operator to limit the search space?
This is a known issue. The short answer is that it has to do with the fact that a multikey index is used (“player” is an array), and the index cannot be constrained on both upper and lower bounds.
This is explained in more detail in the Jira case: https://jira.mongodb.org/browse/SERVER-4155 – “Index bound incorrect?”
There is an open Jira ticket to improve this behavior: https://jira.mongodb.org/browse/SERVER-4180 – “Wrong indexbounds picked for a date range query (regression)” which is slated to be released in version 2.1.2 (this version is subject to change). Please vote for it!