我有一个大集合,我想检索按两个字段排序的结果。但是,我想以一种高效的方式从结果的深处开始检索结果。
例如,如果文档是:
{ age: 25, name: "Gabe" }
{ age: 25, name: "John" }
{ age: 25, name: "Mike" }
{ age: 26, name: "Gabe" }
{ age: 26, name: "John" }
{ age: 26, name: "Mike" }
我想检索按{age:1,name:1}排序的文档。我想直接索引到{age:26,name:“ John”}中,并按照复合索引的顺序检索下N个文档(例如,{age:26,name:“ Mike”})。目的是将分页的搜索结果返回给用户。
答案 0 :(得分:0)
这正是mongodb索引查询的工作方式。
MongoDB索引类似于b树结构。当使用复合索引进行选择和排序时,查询执行程序将开始扫描第一个匹配值的索引,并扫描最后一个匹配项。然后将识别出的文档取回去,以进行进一步的查询。
某些查询可能需要扫描多个索引范围。在示例查询中,扫描索引的单个范围将按顺序查找所有匹配的文档,因此不需要其他排序。
此查询将需要两部分,一部分与第一个年龄和姓名的部分列表匹配,一个与其余的年龄匹配。可以使用"Error on line 1 at column 1: Document is empty
Below is a rendering of the page up to the first error."
运算符来完成。
为了证明这一点,我使用了explain和executeStats选项:
$or
获胜计划显示两次索引扫描,并将其结果传递到合并阶段。请注意,提取阶段不会再进行任何过滤,并且没有内存中排序:
db.collection.explain("executionStats").find({$or:[{age:{$eq:25},name:{$gte:"John"}},{age:{$gt:25}}]}).sort({age:1,name:1})
executionStats部分显示查询执行程序检查了2个索引键和2个文档,此查询返回的文档总数为2:
"winningPlan" : {
"stage" : "SUBPLAN",
"inputStage" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "SORT_MERGE",
"sortPattern" : {
"age" : 1,
"name" : 1
},
"inputStages" : [
{
"stage" : "IXSCAN",
"keyPattern" : {
"age" : 1,
"name" : 1
},
"indexName" : "age_1_name_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"age" : [ ],
"name" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"age" : [
"[25.0, 25.0]"
],
"name" : [
"[\"John\", {})"
]
}
},
{
"stage" : "IXSCAN",
"keyPattern" : {
"age" : 1,
"name" : 1
},
"indexName" : "age_1_name_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"age" : [ ],
"name" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"age" : [
"(25.0, inf.0]"
],
"name" : [
"[MinKey, MaxKey]"
]
}
}
]
}
}
},
(我的笔记本电脑动力不足,因此该查询实际上花了3毫秒)