我有一个表格
的集合{
"fieldA":"ValueA",
"fieldB":"ValueB"
}
其中fieldA始终存在于文档中,但fieldB可能在文档中,也可能不在文档中。
让我们假设我在fieldA上有一个名为fieldAIndex
的索引现在有了这个索引,我希望fieldAIndex
完全涵盖以下查询db.collection.find({"fieldA":"Value1"},{"_id":0,"fieldA":1})
使用explain()运行确认了这种情况:
{
"indexOnly" : true
}
但是当我运行以下查询时出乎意料:
db.collection.find({"fieldA":"Value1","fieldB":{"$exists":true}},{"_id":0,"fieldA":1})
解释也返回
{
"indexOnly" : true
}
鉴于fieldB不在索引中,查询如何才能从索引中返回?索引是否包含有关存在的字段的信息,或者解释是否错误地返回?
提前致谢,
太
答案 0 :(得分:0)
我相信它是MongoDB中查询引擎的工作方式。由于您的第一个标准的项目矩阵几乎满足了它不需要做的任何事情。
以下是该集合的索引:
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"ns" : "test.colTest",
"name" : "_id_"
},
{
"v" : 1,
"key" : {
"fieldA" : 1
},
"ns" : "test.colTest",
"name" : "fieldA_1"
}
]
另外,你没有正确地完成你的研究。尝试向集合中添加更多文档,您的问题将失败。
db.colTest.insert({fieldA:"1"})
运行查询:
db.colTest.find({"fieldA":"value1","fieldB":{"$exists":true}}).explain()
结果如下
{
"cursor" : "BtreeCursor fieldA_1",
"isMultiKey" : false,
"n" : 1,
"nscannedObjects" : 1,
"nscanned" : 1,
"nscannedObjectsAllPlans" : 1,
"nscannedAllPlans" : 1,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"fieldA" : [
[
"value1",
"value1"
]
]
},
"server" : "local:27017"
}
此外,当您以不同方式查询时,explain()的结果会再次更改。
db.colTest.find({"fieldB":{"$exists":true}, "fieldA":"value1"}).explain()
这是输出:
{
"cursor" : "BtreeCursor fieldA_1",
"isMultiKey" : false,
"n" : 1,
"nscannedObjects" : 1,
"nscanned" : 1,
"nscannedObjectsAllPlans" : 1,
"nscannedAllPlans" : 1,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"fieldA" : [
[
"value1",
"value1"
]
]
},
"server" : "local:27017"
}
请仔细阅读文档,以下是参考资料: http://docs.mongodb.org/manual/reference/method/cursor.explain/
我认为确保使用索引的更可靠方法是查看“n”,“nscanned”和“nscannedObjects”。这些字段将为您提供更清晰的图片。
希望这有帮助!
答案 1 :(得分:0)
由于在explain()中报告indexOnly的方式存在问题,因此可以看到此行为。它应该在2.5.4 mongodb版本中修复(https://jira.mongodb.org/browse/SERVER-5759)。
要明确,检查不在索引中的字段的存在不应该在explain()中返回indexOnly = true。这样的任何查询都不会被索引覆盖。
感谢jeffl指点我这个mongodb问题。