今天我注意到,在MongoDB 2.0.2中,$lt和$gt操作符的顺序似乎很重要.

我有一个游戏数据库."player"是两个字符串的数组,代表两个玩家,"endedAtMS"是游戏结束时的时间戳.我创建了这个索引:

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只使用一个操作符来限制搜索空间?

推荐答案

这是一个众所周知的问题.简而言之,这与使用多键索引("player"是一个数组)有关,并且索引不能同时受上界和下界的约束.

这在Jira case 中有更详细的解释:https://jira.mongodb.org/browse/SERVER-4155——"索引界不正确?"

有一个开放的Jira票证可以改善这种行为:https://jira.mongodb.org/browse/SERVER-4180——"为日期范围查询(回归) Select 了错误的索引边界",计划在2.1.2版中发布(此版本可能会发生更改).请投赞成票!

Mongodb相关问答推荐

MongoDB通过查找具有多个数组的对象进行聚合

使用MongoDB 4将根文档替换为数组

为什么 mongoose 在 mongodb 中找不到我的数据

Tableau 与 Mongo DB Atlas by MongoDB 的连接缓存问题

定期自动轮换 MongoDb 集合

Mongo:投影不影响布尔值

使用名为 Object 键的 uuid 创建 mongodb 文档

有谁知道这个错误的修复方法(TypeError: Cannot assign to read only property ‘map’ of object '#')

Pymongo API TypeError: Unhashable dict

如果 mongoDB 服务器正在运行,如何从驱动程序判断

Mongo 无法启动

Meteor mongo 驱动程序可以处理 $each 和 $position 运算符吗?

使用 ObjectId.GenerateNewId() 还是离开 MongoDB 创建一个?

通过 Spring Boot 应用程序访问 mongodb 时的身份验证错误

在 mongodb 中查找字段的所有非不同值

单个模式数组中的多个模式引用 - mongoose

MEAN 堆栈文件上传

在安装的 MongoDB homebrew 中设置 dbpath (Mac OS)

缩短 MongoDB 属性名称值得吗?

Mongoose 为所有嵌套对象添加 _id