MongoDB - 如何尽快获得字段填充率?

MongoDB - how to get fields fill-rates as quickly as possible?

我们有一个非常大的 MongoDB 文档集合,其中包含一些预定义的字段,这些字段可以有值也可以没有。

我们需要收集 fill-rates 个字段,我们编写了一个脚本遍历所有文档并计算每个文档的填充率,问题是处理所有文档需要很长时间。

有没有办法在服务器端使用db.collection.aggregatedb.collection.mapReduce到运行这样的脚本? 它应该有显着的性能改进吗? 它会减慢该集合的其他用途(例如持有主要锁)吗?

据我了解,您想要实现的是对您的文档进行计算,之后您就有了一个可以查询的新 "document"。您不需要存储计算的 "new values"。

如果你不需要在那个文件里面写你的"new values",你可以使用聚合框架。

聚合操作处理数据记录和return计算结果。聚合操作将来自多个文档的值分组在一起,并且可以对分组数据执行各种操作以 return 一个结果。

https://docs.mongodb.com/manual/aggregation/

由于聚合框架有很多功能,我无法为您提供有关如何解决您的问题的更多信息。

回答我自己的问题,我能够使用游标来迁移我的脚本以扫描整个集合,迁移到 map-reduce 查询,并且 运行ning 在集合的样本上似乎位于使用 map-reduce 至少快两倍。

这是旧脚本的工作方式(在 node.js 中):

var cursor = collection.find(query, projection).sort({_id: 1}).limit(limit);
var next = function() {
   cursor.nextObject(function(err, doc) {
      processDoc(doc, next);
   });
};
next();

这是新脚本:

collection.mapReduce(
    function () {
        var processDoc = function(doc) {
            ...
        };
        processDoc(this);
    },
    function (key, values) {
      return Array.sum(values)
    },
    {
      query : query,
      out: {inline: 1}
    },
    function (error, results) {
      // print results
    }
);

processDoc 基本保持不变,但我没有增加全局统计对象上的计数器,而是:

emit(field_name, 1);

运行在 100k 的样本上 ning 旧的和新的,旧的用了 20 秒,新的用了 8.

一些注意事项:

  1. map-reduce 的 limit 选项不适用于分片集合,我不得不查询 _id : { $gte, $lte} 以创建所需的样本大小。
  2. map-reduce 的性能提升选项:jsMode : true 也不适用于分片集合(可能会进一步提高性能),它可能会 运行 它在每个分片上手动工作以获得该功能。