1

我有表格的集合

{
    "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 不在索引中,查询如何仅从索引返回?索引是否包含有关存在的字段的信息或解释是否返回不正确?

提前致谢,

马特。

4

2 回答 2

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”。这些字段将为您提供更清晰的画面。

希望这可以帮助!

于 2013-10-11T17:59:41.087 回答
0

由于在 explain() 中报告 indexOnly 的方式存在问题,因此可以看到此行为。它将在 2.5.4 mongodb 版本中修复(https://jira.mongodb.org/browse/SERVER-5759)。

明确地说,检查索引中不存在的字段不应该在 explain() 中返回 indexOnly=true。任何这样的查询都不会被索引覆盖。

感谢 jeffl 向我指出这个 mongodb 问题。

于 2013-10-13T12:55:37.903 回答