为什么Mongo在执行IXSCAN之后在FETCH中查询空过滤器 [英] Why Mongo query for null filters in FETCH after performing IXSCAN
问题描述
根据 Mongo文档,
{ item : null }
查询匹配包含以下内容的文档:item
字段,其值为null
或不包含item
字段.
The
{ item : null }
query matches documents that either contain theitem
field whose value isnull
or that do not contain theitem
field.
我找不到有关此内容的文档,但据我所知,两种情况(值是null
或字段缺失)都以null
的形式存储在索引中.
I can't find documentation for this, but as far as I can tell, both cases (value is null
or field is missing) are stored in the index as null
.
因此,如果我先执行db.orders.createIndex({item: 1})
,然后再执行db.orders.find({item: null})
,则我希望IXSCAN
查找包含值null
的item
字段或不包含item
的所有文档.字段,只有这些文档.
So if I do db.orders.createIndex({item: 1})
and then db.orders.find({item: null})
, I would expect an IXSCAN
to find all documents that either contain the item
field whose value is null
or that do not contain the item
field, and only those documents.
那么为什么db.orders.find({item: null}).explain()
在执行IXSCAN
之后在FETCH
阶段执行filter: {item: {$eq: null}}
?可能需要过滤哪些文件?
So then why does db.orders.find({item: null}).explain()
perform filter: {item: {$eq: null}}
in the FETCH
stage after it performs an IXSCAN
? What possible documents could need to be filtered out?
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "temp.orders",
"indexFilterSet" : false,
"parsedQuery" : {
"item" : {
"$eq" : null
}
},
"winningPlan" : {
"stage" : "FETCH",
"filter" : {
"item" : {
"$eq" : null
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"item" : 1
},
"indexName" : "item_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"item" : [
"[null, null]"
]
}
}
},
"rejectedPlans" : [ ]
},
"serverInfo" : {
"host" : "Andys-MacBook-Pro-2.local",
"port" : 27017,
"version" : "3.2.8",
"gitVersion" : "ed70e33130c977bda0024c125b56d159573dbaf0"
},
"ok" : 1
}
我想也许undefined
的值会被索引为null
,但是简单的实验排除了这一点:
I thought maybe undefined
values would get indexed as null
, but simple experimentation rules this out:
> db.orders.createIndex({item: 1})
{
"createdCollectionAutomatically" : true,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
> db.orders.insert({item: undefined})
WriteResult({ "nInserted" : 1 })
> db.orders.find({item: {$type: 6}}).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "temp.orders",
"indexFilterSet" : false,
"parsedQuery" : {
"item" : {
"$type" : 6
}
},
"winningPlan" : {
"stage" : "FETCH",
"filter" : {
"item" : {
"$type" : 6
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"item" : 1
},
"indexName" : "item_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"item" : [
"[undefined, undefined]"
]
}
}
},
"rejectedPlans" : [ ]
},
"serverInfo" : {
"host" : "Andys-MacBook-Pro-2.local",
"port" : 27017,
"version" : "3.2.8",
"gitVersion" : "ed70e33130c977bda0024c125b56d159573dbaf0"
},
"ok" : 1
}
推荐答案
空相等匹配谓词(例如{"a.b": null}
)的语义非常复杂,因为字段可能包含仅索引扫描不足以包含的子文档.提供正确的结果.
The semantics for a null equality match predicate (e.g. {"a.b": null}
) are complicated enough because a field could contain subdocuments that an index scan alone isn't enough to provide the correct result.