Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Order of $lt and $gt in MongoDB range query

Tags:

mongodb

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?

like image 476
StefanMK Avatar asked Mar 27 '12 18:03

StefanMK


People also ask

Does order of query matter MongoDB?

Generally, the order of query operators doesn't matter...

Does MongoDB maintain array order?

yep MongoDB keeps the order of the array.. just like Javascript engines..

Is $gt for greater than or equal to the value?

Definition. $gt selects those documents where the value of the field is greater than (i.e. > ) the specified value . For most data types, comparison operators only perform comparisons on fields where the BSON type matches the query value's type.


2 Answers

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!

like image 140
Marc Avatar answered Oct 28 '22 23:10

Marc


This has been fixed in version '2.1.2'.

As per: https://jira.mongodb.org/browse/SERVER-4180

AWESOME!

like image 29
Lenny Linus Avatar answered Oct 28 '22 23:10

Lenny Linus