MongoDB(WiredTiger)返回的计数不正确。

16

这听起来很奇怪,我希望我做错了什么,但我的MongoDB集合返回的Count比我的集合中的数量少了一个。

我有一个(我确定)有359671个文档的集合。但是count()命令返回359670个文档。

我正在使用mongo shell执行count()命令:

rs0:PRIMARY> db.COLLECTION.count()
359670

这是错误的。

它没有找到我集合中的每一个文档。

如果我提供以下查询给计数器,我会得到正确的结果:

rs0:PRIMARY> db.COLLECTION.count({_id: {$exists: true}})
359671

我认为这是WiredTiger的一个bug。据我所知,每个文档都具有相同的定义,即一个_id字段,整数范围从0到359670,以及一个BinData字段。我在旧存储引擎(或Mongo 2)中没有遇到过这个问题,这可能是引起问题的原因。

这是我做错了什么吗?我不想使用{_id: {$exists: true}}查询,因为那需要更长的时间来完成。


1
你正在使用分片集群吗?如果是的话,请参阅http://docs.mongodb.org/manual/reference/method/db.collection.count/#sharded-clusters - JohnnyHK
我没有使用分片集群,但是谢谢你的建议。 - James
2个回答

29
根据此问题,如果mongodb经历了严重的崩溃并未正常关闭,则可能发生此行为。 如果没有发出任何查询,mongodb可能只会回退到收集的统计信息。

根据文章,调用db.COLLECTION.validate(true)应该重置计数器。

13

根据文档所述,如果不使用查询参数进行调用,则 db.collection.count() 返回基于集合元数据的结果:

这可能导致近似计数。特别是:

  • 在分片集群上,得到的计数将无法正确过滤孤立文档。

  • 在非正常关闭之后,计数可能不正确。

当使用查询参数时,就像您在第二个查询中使用的{_id: {$exists: true}},它会强制 count 不使用集合的元数据,而是扫描集合。


Mongo 4.0.3 开始count() 被认为是不推荐使用的,建议使用以下替代方法:

db.collection.countDocuments({})

在底层实际执行以下“昂贵”的但准确的聚合操作(昂贵是因为需要扫描整个集合以计算记录数):

db.collection.aggregate([{ $group: { _id: null, n: { $sum: 1 } } }])
db.collection.estimatedDocumentCount()

这个函数执行与db.collection.count()完全相同的操作(实际上是count的一个包装器),使用集合的元数据。

因此,这几乎是瞬时完成的,但在上述特定情况下可能会导致近似结果。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接