Mongodb $exists 查询不返回正确的文档

Posted

技术标签:

【中文标题】Mongodb $exists 查询不返回正确的文档【英文标题】:Mongo $exists query does not return correct documents 【发布时间】:2012-02-25 10:36:46 【问题描述】:

老实说,我不明白这怎么可能:

> db.ts.find("bcoded_metadata" :  "$exists" : true  ).count()
199049
> db.ts.find("bcoded_metadata" :  "$exists" : false  ).count()
0
> db.ts.count()
2507873

我认为第一个和第二个查询的总和必须等于第三个。

我需要从集合中选择“bcoded_metadata”不存在但查询不返回任何内容的所有元素。 当我在简单的 python 脚本中迭代这个集合并手动检查“bcoded_metadata”是否存在时,一切都按预期工作。

from pymongo import Connection
connection = Connection('127.0.0.1', 27017)
db = connection.data
c = 0
for item in db.ts.find():
    if not "bcoded_metadata" in item.keys():
            c+= 1
print c



python test.py 
2308824

这是正确答案。

问题的根源在哪里?

索引:

> db.ts.getIndexes();
[
        
                "name" : "_id_",
                "ns" : "data.ts",
                "key" : 
                        "_id" : 1
                ,
                "v" : 0
        ,
        
                "_id" : ObjectId("4f3c299b4c4a5ccfddbe4069"),
                "ns" : "data.ts",
                "key" : 
                        "last_seen" : 1
                ,
                "name" : "last_seen_1",
                "v" : 0
        ,
        
                "_id" : ObjectId("4f3c2cef4c4a5ccfddbe406a"),
                "ns" : "data.ts",
                "key" : 
                        "attempts" : -1
                ,
                "name" : "attempts_-1",
                "v" : 0
        ,
        
                "_id" : ObjectId("4f4279ed6aca13be31acbe6d"),
                "ns" : "data.ts",
                "key" : 
                        "bcoded_metadata" : 1
                ,
                "name" : "bcoded_metadata_1",
                "sparse" : true,
                "v" : 0
        
]

【问题讨论】:

您的查询是从 mongo shell 还是驱动程序? @marcolinux 查询是从 from shell 执行的。 python 脚本显然是通过驱动程序工作的。 也许是这个错误? jira.mongodb.org/browse/SERVER-3918 @marcolinux 确实如此,谢谢!但是我应该使用什么样的时间解决方案?该链接不提供任何内容。 你需要找到另一种方法。但这很大程度上取决于我们的数据结构。例如,您可以强制bcoded_metadata 为实际值(例如zzzz),将索引从sparse 更改为正常并暂时查询该值。但这取决于数据的填充方式以及应用程序的其他典型参数。 【参考方案1】:

这是因为您对bcoded_metadata 使用了稀疏索引。如果您在 bcoded_metadata 上有一个稀疏索引,那么该索引将不包含没有字段 bcoded_metadata 的文档。没有bcoded_metadata 字段的文档不属于您的原始查询,因此“count”将返回 0。

如果你只运行 find:db.ts.find("bcoded_metadata" : "$exists" : false ) 那么你也不会得到任何结果。您可以使用非稀疏索引,也可以使用db.ts.count(); 进行完整计数并减去db.ts.find("bcoded_metadata" : "$exists" : true ) 的结果。

有一个 JIRA 票可以对其进行更多解释,并且可以在 MongoDB 收到错误/警告消息时进行跟踪:https://jira.mongodb.org/browse/SERVER-3918

【讨论】:

实际上我需要遍历没有“bcoded_metadata”的文档。我该怎么办?有没有办法强制执行密集索引?因为 ensureIndex("bcoded_metadata":1,sparce:false);没有按预期工作,之后我仍然有稀疏索引。 好的,我刚刚删除了“bcoded_metadata”的索引,它解决了问题。谢谢。 与其删除该索引,不如考虑将其设置为 not 稀疏索引。默认情况下索引不是稀疏的,所以这是您自己完成的。

以上是关于Mongodb $exists 查询不返回正确的文档的主要内容,如果未能解决你的问题,请参考以下文章

mongodb 查询表达式

MongoDB(课时12 字段判断)

sql 查询的正确语法和 WHERE EXISTS 替代方案

mongodb使用小点

通过 Management Studio 在脚本中使用 EXISTS 返回错误值

返回 MongoDB 中的每个特定对象