14

这听起来很奇怪,我希望我做错了什么,但我的MongoDB收藏正在我的收藏中退还Count一个。

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

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

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

这是不正确的。

它不是在我的收藏中找到每一个文件。

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

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

我相信这是 WiredTiger 中的一个错误。据我所知,每个文档都有相同的定义,一个从 0 到 359670 的整数的 _id 字段和一个 BinData 字段。较旧的存储引擎(或 Mongo 2,两者都可能导致问题)没有这个问题。

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

4

2 回答 2

27

根据这个问题,如果 mongodb 遇到硬崩溃并且没有正常关闭,则可能会发生此行为。如果不发出任何查询,mongodb 可能只是回退到收集的统计信息。

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

于 2017-02-13T14:36:08.910 回答
10

如文档中所述,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),它使用集合的元数据。

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

于 2018-10-26T08:40:50.857 回答