我正在尝试使用覆盖索引在我的使用mongodb的应用上实现词干文本搜索。
我有以下索引集:
ensureIndex({st: 1, n: 1, _id: 1});
但是当我在查询中运行explain()时,无论我做什么,我都无法将indexOnly读为true。
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名为spl_development.merchants {$ query:{st:{$ regex:“cr”,$ options:“i “}},$ explain:true} Mon 7月15日10:47:26 [conn14]查询spl_development.merchants查询:{$ query:{st:{$ regex:”cr“,$ options:”i“}}, $ explain:true} ntoreturn:0 keyUpdates:0 lock(micros)r:212 nreturned:1 reslen:393 0ms
因此投影不会被发送到mongod层,只是在应用层中处理它。不理想!
这已被认为是mongoid中的一个错误,可以在这里跟踪: https://github.com/mongoid/mongoid/issues/3142
答案 0 :(得分:8)
我希望您的查询不能使用覆盖索引,因为您有一个包含在索引中的数组的字段。这在"isMultiKey" : true
的解释中提出。
如文档(Create Indexes that Support Covered Queries)中所述:
如果集合中任何文档中的任何索引字段包含数组,则MongoDB无法使用覆盖查询。如果索引字段是数组,则索引将成为多键索引,并且不支持覆盖查询。
答案 1 :(得分:1)
我无法重现2.2.2中的问题,但将.sort({n: 1, _id: 1})
添加到链中。因为你没有排序,你要求mongo希望使用的任何find
命令中的文档,如果这与命令中的顺序(例如$natural
)不匹配它仍然需要阅读文档。
db.merchants.find({st: "Blue"}, {n:1,_id:1}).sort({n: 1, _id: 1}).explain()