我有一个名为"EN“的集合,我创建了一个索引如下:
db.EN.createIndex( { "Prod_id": 1 } );当我运行db.EN.getIndexes()时,我得到了以下内容:
[{ "v": 2, "key": {
"_id": 1 }, "name": "_id_" }, { "v": 2, "key": {
"Prod_id": 1 }, "name": "Prod_id_1" }]但是,当我运行以下查询时:
db.EN.find({'Icecat-interface.Product.@Prod_id':'ABCD'})
.explain()我明白了:
{ "explainVersion": "1", "queryPlanner": {
"namespace": "Icecat.EN",
"indexFilterSet": false,
"parsedQuery": {
"ICECAT-interface.Product.Prod_id": {
"$eq": "ABCD"
}
},
"queryHash": "D12BE22E",
"planCacheKey": "9F077ED2",
"maxIndexedOrSolutionsReached": false,
"maxIndexedAndSolutionsReached": false,
"maxScansToExplodeReached": false,
"winningPlan": {
"stage": "COLLSCAN",
"filter": {
"ICECAT-interface.Product.Prod_id": {
"$eq": "ABCD"
}
},
"direction": "forward"
},
"rejectedPlans": [] }, "command": {
"find": "EN",
"filter": {
"ICECAT-interface.Product.Prod_id": "ABCD"
},
"batchSize": 1000,
"projection": {},
"$readPreference": {
"mode": "primary"
},
"$db": "Icecat" }, "serverInfo": {它使用的是COLLSCAN而不是索引,为什么会发生这种情况?
MongoDB版本为5.0.9-8
谢谢
编辑(和解决方案)
它的前面是字段名"@“,而索引是在没有这个字符的情况下创建的,所以根本没有捡到它。
有一次,我使用字段名创建了一个新的索引,就像它应该的那样,它正常工作。
不过,看到索引的工作原理和最佳实践是很有趣的。
发布于 2022-10-21 14:08:39
查找操作定义为
.find({'Icecat-interface.Product.@Prod_id':'ABCD'})什么是Icecat-interface.Product.@?
explain输出中的parsedQuery确认MongoDB试图查找一个文档,该文档的值为"ABCD",其值与您所命名的字段名不同。根据您提供的explain,这个字段名是"ICECAT-interface.Product.Prod_id"。由于查询的字段名与索引的字段名不同,MongoDB无法使用索引执行操作。
与此略有关联的是,@输出中没有find中使用的explain字符。这似乎是因为用于生成explain的实际操作略有不同。这也是显而易见的事实,解释包括一个batchSize of 1000,该操作在被显示为被解释的操作中缺失。
根据Icecat-interface.Product.@前缀应该是什么,解决方案可能只是将其从find本身的查询谓词中删除。
编辑以响应comment和编辑问题。关于第一项评论:
当我运行
:.find({'Prod_id':'ABCD'})时,它使用COLLSCAN,这对我来说是错误的,因为我在该字段上有一个索引,除非我在这里遗漏了什么
如果查询使用了MongoDB的第一个键,那么它将使用索引。因此,{ y: 1 }上的索引不符合.find({ x: 1})查询的使用条件。类似于一般的x和y示例,Icecat-interface.Product.Prod_id和Prod_id是不同的字段名。因此,如果您对一个查询而另一个查询只存在一个索引,则集合扫描是数据库执行该查询的唯一方法。
这将与问题的编辑部分重叠。在已编辑的问题中,新的解释计划使用索引成功地显示了数据库。但是,该索引是{ "ICECAT-interface.Product.Prod_id": 1 },它是,而不是--最初显示在集合({ "Prod_id": 1 })上创建或显示的索引。
此外,您还提到“即使我知道的产品在DB中,也不会得到任何结果”。数据库中的哪个字段包含正在搜索的值('ABCD')?这将直接告诉您返回的结果以及用于查找结果的索引。请记住,即使数据库中不存在任意字段,也可以搜索MongoDB中的任意字段。
我建议特别注意正在使用的名称空间和字段名。除非这个{ "ICECAT-interface.Product.Prod_id": 1 }索引是在收集db.EN.getIndexes()输出之后创建的,否则您可能无意中连接到不同的系统或名称空间,因为该索引肯定存在于某个地方。
在我写这篇文章的时候,基于你的live comments,你似乎已经解开了字段名的谜团。
https://stackoverflow.com/questions/74154625
复制相似问题