考虑正在查询的示例文档的集合,如问题中所示:
{ _id: 1, type: "person", image: "i-1", age: 19, "fld": 12 },
{ _id: 2, type: "person", image: "i-2", age: 22, "fld": 121 },
{ _id: 3, type: "thing", image: "i-99", age: 29, "fld": 1212 }, // 'type' not 'person'
{ _id: 4, type: "person", age: 31, "fld": 12121 }, // 'image' missing
{ _id: 5, type: "person", image: "i-3", age: 13, "fld": 121212 },
{ _id: 6, type: "person", age: 43, "fld": 1212121 }, // 'image' missing
{ _id: 7, type: "person", image: "i-4", age: 20, "fld": 1 }
如果我已经拥有这些字段,是否需要将它们包含在索引中
过滤?或者它是否已经通过部分过滤器表达式知道
而我只查询未修复的内容?
创建一个索引:
db.collection.createIndex( { type: 1, age: -1 },
{
partialFilterExpression: {
type: 'person',
image: { $exists: true }
}
}
)
请注意,索引字段仅在 type 和 age 上。为什么?这在下面的索引使用验证中进行了解释。
查询:
db.collection.find( { type: "person", image: { $exists: true } } ).sort( { age: -1 } )
结果:
查询以排序顺序返回预期的过滤文档和。
{ "_id" : 2, "type" : "person", "image" : "i-2", "age" : 22, "fld" : 121 }
{ "_id" : 7, "type" : "person", "image" : "i-4", "age" : 20, "fld" : 1 }
{ "_id" : 1, "type" : "person", "image" : "i-1", "age" : 19, "fld" : 12 }
{ "_id" : 5, "type" : "person", "image" : "i-3", "age" : 13, "fld" : 121212 }
索引使用验证:
可以通过使用explain方法生成查询计划来验证索引的使用情况:
db.collection.find( { type: "person", image: { $exists: true } } ).sort( { age: -1 } ).explain()
计划输出显示过滤器和排序操作的索引使用情况。这在计划中被标记为 IXSCAN(索引扫描)和 SORT 阶段的缺席。这是该查询的索引的正确用法。
在索引定义中,type + age 这两个字段指定了一个复合索引。这是要求将索引应用于type(用于过滤)和age(用于排序)。字段image 不能在索引定义中指定,因为它不与相等条件一起使用 条件(使用$exists);如果指定,索引将不会用于以下排序字段(来自documentation):
索引可以支持对非前缀子集的排序操作
索引键模式。为此,查询必须包含相等
排序键之前的所有前缀键的条件。
查询计划(其中的一部分):
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.persons",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"type" : {
"$eq" : "person"
}
},
{
"image" : {
"$exists" : true
}
}
]
},
"queryHash" : "25E877F5",
"planCacheKey" : "C9D745BE",
"winningPlan" : {
"stage" : "FETCH",
"filter" : {
"image" : {
"$exists" : true
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"type" : 1,
"age" : -1
},
"indexName" : "type_1_age_-1",
"isMultiKey" : false,
"multiKeyPaths" : {
"type" : [ ],
"age" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : true,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"type" : [
"[\"person\", \"person\"]"
],
"age" : [
"[MaxKey, MinKey]"
]
}
}
}, ...