Подтвердить что ты не робот

Порядок запросов $lt и $gt в запросе диапазона MongoDB

Сегодня я заметил, что порядок, в котором заданы операторы $lt и $gt, кажется, имеет значение в MongoDB 2.0.2.

У меня есть база данных игр. "player" - это массив из двух строк, представляющих обоих игроков, "endAtMS" - это метка времени, когда игра закончилась. Я создал этот индекс:

db.games.ensureIndex({player:1,endedAtMS:-1})

Чтобы получить 30 из моих игр, которые были закончены в определенный промежуток времени, упорядочены по времени окончания игр, я делаю:

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
            ]
        ]
    }
}

Кажется, все работает нормально. Однако, когда я изменяю порядок $lt и $gt в запросе выше, я получаю следующее:

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
            ]
        ]
    }
}

Как вы можете видеть, 126 документов необходимо отсканировать, чтобы получить 30 документов для результата. Если вы посмотрите на indexBounds в выводе объяснения, кажется, что для ограничения пространства поиска в индексе используется только первый оператор.

Что я пропущу? Почему Mongo использует только один оператор для ограничения пространства поиска?

4b9b3361

Ответ 1

Это известная проблема. Короткий ответ заключается в том, что он связан с тем, что используется мультикидный индекс ( "игрок" - это массив), и индекс не может быть ограничен как верхней, так и нижней границей.

Это более подробно объясняется в случае Jira: https://jira.mongodb.org/browse/SERVER-4155 - "Недопустимый индекс?"

Для улучшения этого поведения существует открытый билет Jira: https://jira.mongodb.org/browse/SERVER-4180 - "Неверные индексы, выбранные для запроса диапазона дат (регрессии)" который планируется выпустить в версии 2.1.2 (эта версия может быть изменена). Пожалуйста, проголосуйте за него!