我在MongoDB中保存游戏文档。除其他外,文件包含玩家的名字(姓名),游戏结束的时间(endMS)和游戏的类型(类型)。类型可以有五个不同的值中的一个。
我需要按照游戏结束时间排序的玩家搜索所有已完成的游戏,并按照游戏结束时间排序的具有特定游戏类型的玩家搜索所有已完成的游戏。
两个查询的示例都是
db.games.find({名: “斯蒂芬”,endMS:{$ GT:0}})。排序({endMS:-1})
和
db.games.find({名: “斯蒂芬”,类型: “BLI”,endMS:{$ GT:0}})。排序({endMS:-1})
您可以使用索引
db.games.ensureIndex({名:1,endMS:-1})
和
db.games.ensureIndex({名称:1,类型:1,endMS:-1})
快速访问。
现在我只想与一个指数相处:
db.games.ensureIndex({名:1,endMS:-1,类型:1})
第一个查询或课程仍然正常运行。第二个查询的想法是Mongo可能需要在扫描索引时跳过一些条目,但只需要访问查询最终返回的文档,因为已经可以在索引中检查“类型”。这应该足够快,以满足我的需求。
然而,使用explain()MongoDB告诉我在查询数据库时需要“scanAndOrder”。
db.games.find({名: “斯蒂芬”,类型: “BLI”,endMS:{$ GT:0}})排序({endMS:-1})。。解释()
{
"cursor" : "BtreeCursor name_1_endMS_-1_type_1",
"isMultiKey" : false,
"n" : 1,
"nscannedObjects" : 1,
"nscanned" : 22,
"nscannedObjectsAllPlans" : 4,
"nscannedAllPlans" : 25,
"scanAndOrder" : true,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"name" : [
[
"Stefan",
"Stefan"
]
],
"endMS" : [
[
Infinity,
0
]
],
"type" : [
[
"bli",
"bli"
]
]
},
"server" : "localhost:27017",
"filterSet" : false
}
如上所述,nscannedObjects和nscanned是预期的,但我想知道为什么Mongo说scanAndOrder:true。
根据文件: “scanAndOrder是一个布尔值,当查询无法使用索引中的文档顺序返回排序结果时,它是真的:MongoDB必须在从光标接收文档后对文档进行排序。”
据我所知,文件应该在索引中订购,只需要跳过一些不影响订单的文件。
那么为什么MongoDB在这里使用scanAndOrder?
答案 0 :(得分:3)
这似乎是MongoDB 2.6.0-rc0中的一个错误。所有这些都在MongoDB 2.4.9中按预期工作。
答案 1 :(得分:0)
Stefan在这里报告了这个问题:http://jira.mongodb.org/browse/SERVER-12935并且在2.6.0-rc0之后解决了scanAndOrder问题,但是解释输出存在一些挥之不去的问题。
答案 2 :(得分:-2)
http://docs.mongodb.org/manual/reference/glossary/
自然顺序: 数据库在磁盘上存储文档的顺序。通常,磁盘上文档的顺序反映了插入顺序,除非文档在内部移动,因为更新操作会增加其大小。在上限集合中,插入顺序和自然顺序是相同的,因为文档不会在内部移动。对于没有参数的find()查询,MongoDB以正向自然顺序返回文档。对于使用$ natural:-1参数排序的find()查询,MongoDB以反向自然顺序返回文档。见$ natural。
您对插入顺序==索引顺序的假设是错误的。