MongoDB查询由索引覆盖但$ exists字段未包含在索引中

时间:2013-10-11 15:47:49

标签: mongodb indexing exists explain

我有一个表格

的集合
{
    "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不在索引中,查询如何才能从索引中返回?索引是否包含有关存在的字段的信息,或者解释是否错误地返回?

提前致谢,

2 个答案:

答案 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问题。