5

我正在尝试使用覆盖索引在使用 mongodb 的应用程序上实现词干文本搜索。

我有以下索引集:

ensureIndex({st: 1, n: 1, _id: 1});

但是,当我在查询上运行 explain() 时,无论我做什么,我都无法让 indexOnly 读取为真。

db.merchants.find({st: "Blue"}, {n:1,_id:1}).explain()
{
    "cursor" : "BtreeCursor st_1_n_1__id_1",
    "nscanned" : 8,
    "nscannedObjects" : 8,
    "n" : 8,
    "millis" : 0,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "isMultiKey" : true,
    "indexOnly" : false,
    "indexBounds" : {
        "st" : [
            [
                "Blue",
                "Blue"
            ]
        ],
        "n" : [
            [
                {
                    "$minElement" : 1
                },
                {
                    "$maxElement" : 1
                }
            ]
        ],
        "_id" : [
            [
                {
                    "$minElement" : 1
                },
                {
                    "$maxElement" : 1
                }
            ]
        ]
    }
}

我已经发现索引中键的顺序很重要。例如,如果我使用 {_id, n:1, st:1} 它根本没有使用这个索引来执行查询。我还在某处读到,太少的文档可能会使用 explain() 触发不可预测的行为,因为多种策略同样快。但是在这种情况下,我看到它使用了正确的索引,但它不仅仅使用了索引。这是怎么回事?

我正在使用 mongoid,我相信 mongo 2.0.8。

更新:

切换到使用 Mongoid v3.1.4 和 mongod v2.2

这是 mongod 从 mongoid 看到的查询: Mon Jul 15 10:47:26 [conn14] runQuery called spl_development.merchants { $query: { st: { $regex: "cr", $options: "i" } } , $explain: true } Mon Jul 15 10:47:26 [conn14] query spl_development.merchants query: { $query: { st: { $regex: "cr", $options: "i" } }, $explain: true } ntoreturn:0 keyUpdates:0 locks(micros) r:212 nreturned:1 reslen:393 0ms

所以投影不会被发送到 mongod 层,只是在应用层处理它。不理想!

这已被认为是 mongoid 中的一个错误,可以在此处进行跟踪: https ://github.com/mongoid/mongoid/issues/3142

4

2 回答 2

8

我希望您的查询不能使用覆盖索引,因为您有一个包含在索引中的数组的字段。这是在解释中建议的"isMultiKey" : true

如文档中所述(创建支持涵盖查询的索引):

如果集合中任何文档中的任何索引字段包含数组,则 MongoDB 无法使用覆盖查询。如果索引字段是数组,则索引变为多键索引,无法支持覆盖查询。

于 2013-01-07T06:39:21.477 回答
1

我无法重现 2.2.2 中的问题,但添加.sort({n: 1, _id: 1})到链中。因为您没有排序,所以您find以 mongo 希望使用的任何顺序请求文档,如果这与索引中的顺序(例如 order)不匹配,$natural它仍然必须阅读文档。

db.merchants.find({st: "Blue"}, {n:1,_id:1}).sort({n: 1, _id: 1}).explain()
于 2013-01-07T06:32:16.697 回答