很抱歉,我是MongoDB的新手。
假设您有一个名为“学生”的集合,并在一个名为“成绩”的字段上建立了索引。其中哪个会更快?
db.students.find({"grade": {$gte: 50}, "grade": {$lt: 90}})
db.students.find().min("grade": 50).max("grade": 90)
除了能够为第二个选项提供hint
之外,第二个选项是否存在并且具有优势?
答案 0 :(得分:0)
第一个查询将更快,因为它允许在索引上进行边界。使用explain时最好看到这一点。
例如:
db.stack.find({ "grade" : { "$lt" : 90, "$gt" : 50 } }).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.stack",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"grade" : {
"$lt" : 90
}
},
{
"grade" : {
"$gt" : 50
}
}
]
},
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"grade" : 1
},
"indexName" : "grade_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"grade" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"grade" : [
"(50.0, 90.0)"
]
}
}
},
"rejectedPlans" : [ ]
},
上方的indexBounds
字段显示查询仅扫描索引的子集,尤其是50到90之间的键。
相比之下,另一种查询形式是扫描索引范围,然后解析结果的游标以执行min
和max
函数:
db.stack.find().min({ "grade" : 50 }).max({"grade" : 90 }).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.stack",
"indexFilterSet" : false,
"parsedQuery" : {
},
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"grade" : 1
},
"indexName" : "grade_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"grade" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
}
}
},
"rejectedPlans" : [ ]
},
请注意上面的indexBounds
是空的。
有道理吗?
另一个重要说明:问题中列出的查询将无法按预期方式运行,因为它将仅以当前形式应用$lte : 90
过滤器。
在单个字段上应用多个过滤器的查询将需要使用$and operator对多个条件执行逻辑AND
。在上面的示例中,我将多个过滤器组合为一个条件:
{ "grade" : { "$lt" : 90, "$gt" : 50 } }
这应该与:
{
"$and" : [
{ grade : { "$gt" : 50 } },
{ grade: { "$lt" : 90 } }
]
}