我在mongo集合上设置了复合索引,无论我如何具体定位前缀,我都无法获得使用它的查询。
如何创建索引:
db.collection.createIndex({"insert_time":-1,"name":"text"},{background: true})
索引规范输出:
db.collection.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "db.collection"
},
{
"v" : 2,
"key" : {
"insert_time" : -1,
"_fts" : "text",
"_ftsx" : 1
},
"name" : "insert_time_-1_name_text",
"ns" : "db.collection",
"background" : true,
"weights" : {
"name" : 1
},
"default_language" : "english",
"language_override" : "language",
"textIndexVersion" : 3
}
]
但是当我在insert_time上运行最简单的查询时,explain()
告诉我,获胜的计划是进行COLLSCAN,而不使用任何索引:
db.collection.find({"insert_time": ISODate("2018-08-
05T19:00:00Z")}).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "db.collection",
"indexFilterSet" : false,
"parsedQuery" : {
"insert_time" : {
"$eq" : ISODate("2018-08-05T19:00:00Z")
}
},
"winningPlan" : {
"stage" : "COLLSCAN",
"filter" : {
"insert_time" : {
"$eq" : ISODate("2018-08-05T19:00:00Z")
}
},
"direction" : "forward"
},
"rejectedPlans" : [ ]
},
"serverInfo" : {
"host" : "foo",
"port" : 0000,
"version" : "3.4.10",
"gitVersion" : "078f28920cb24de0dd479b5ea6c66c644f6326e9"
},
"ok" : 1
}
即使索引被指定为“复合索引”,但我的理解是我应该能够通过“前缀”进行搜索,在这种情况下,insert_time
是。关于mongo为什么不使用我的索引的任何想法?
答案 0 :(得分:3)
text
的索引是sparse by default。
索引中的非文本索引字段不引用text
索引(reference)中的文档
对于包含文本索引键以及其他类型的键的复合索引,只有文本索引字段才能确定索引是否引用文档。其他键不能确定索引是否引用文档。
=>在没有文本索引字段的情况下使用前缀索引时,结果可能不完整
关于这种情况(sparse Index and Incomplete Results),MongoDB指出:
如果索引稀疏会导致查询和排序操作的结果集不完整,则除非hint()明确指定索引,否则MongoDB不会使用该索引。
如果使用hint('yourTextIndexName')
,则使用索引。
因此,OP的情况是预期的行为,但没有充分记录。
答案 1 :(得分:0)
这感觉像是个错误。
我能够使用MongoDB 3.6.7重现您在自己的数据集上看到的行为。我暗示了有问题的索引,并且查询计划程序无法在前缀字段上绑定(我在year
上进行了直接匹配):
"indexBounds" : {
"year" : [
"[MinKey, MaxKey]"
],
"_fts" : [
"[MinKey, MaxKey]"
],
"_ftsx" : [
"[MinKey, MaxKey]"
]
},
compound text indexes的文档中没有任何语句表明无法使用文本索引的前缀部分。 index prefixes上的文档也没有包含有关限制的任何语言。
编辑:
我创建了一个server ticket来报告此行为,并尝试获取有关此错误或错误的更多信息。