MongoDB 汇总所有前几周的每周总和

标签 mongodb mapreduce mongodb-query aggregation-framework

我在 MongoDB 中有一系列文档。一个示例文档是

{ 
  createdAt: Mon Oct 12 2015 09:45:20 GMT-0700 (PDT),
  year: 2015,
  week: 41 
}

想象一下,这些事件跨越一年中的所有几周,而且同一周内可能会有很多次事件。我想以这样一种方式汇总它们,即结果值是每周的总和以及之前所有周的总文档数。

所以如果一年的第一周有 10 个,第二周有 20 个,结果可能是这样的

[{ week: 1, total: 10, weekTotal: 10},
 { week: 2, total: 30, weekTotal: 20}]

创建一个聚合来查找 weekTotal 非常简单。包括显示第一部分的投影

db.collection.aggregate([
  {
    $project: {
      "createdAt": 1,
      year: {$year: "$createdAt"},
      week: {$week: "$createdAt"},
      _id: 0
    }
  },
  {
    $group: {
      _id: {year: "$year", week: "$week"},
      weekTotal : { $sum : 1 }
    }
  },
]);

但事实证明,要根据这一周和之前的那几周来计算总和是很棘手的。

最佳答案

聚合框架无法做到这一点,因为所有操作一次只能有效地查看一个文档或分组边界。为了在“服务器”上执行此操作,您需要一些可以访问全局变量的东西来保持“运行总计”,这意味着 mapReduce 代替:

db.collection.mapReduce(
    function() {

        Date.prototype.getWeekNumber = function(){
            var d = new Date(+this);
            d.setHours(0,0,0);
            d.setDate(d.getDate()+4-(d.getDay()||7));
            return Math.ceil((((d-new Date(d.getFullYear(),0,1))/8.64e7)+1)/7);
        };


        emit({ year: this.createdAt.getFullYear(), week: this.createdAt.getWeekNumber() }, 1);
    },
    function(values) {
        return Array.sum(values);
    },
    { 
        out: { inline: 1 },
        scope: { total: 0 },
        finalize: function(value) {
            total += value;
            return { total: total, weekTotal: value }
        }
    }
)

如果您可以接受发生在“客户端”上的操作,那么您需要遍历聚合结果并类似地求和:

var total = 0;

db.collection.aggregate([
    { "$group": {
        "_id": {
            "year": { "$year": "$createdAt" },
            "week": { "$week": "$createdAt" }
        },
        "weekTotal": { "$sum": 1 }
    }},
    { "$sort": { "_id": 1 } }
]).map(function(doc) {
    total += doc.weekTotal;
    doc.total = total;
    return doc;
});

这完全取决于这是否需要在服务器或客户端上发生对您来说最有意义。但是由于聚合管道没有这样的“全局变量”,因此您可能不应该在不输出到另一个集合的情况下查看它以进行任何进一步处理。

关于MongoDB 汇总所有前几周的每周总和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33577908/

相关文章:

json - Mongo forEach 查询

hadoop - yarn : How to run MapReduce jobs with lot of mappers comparing to cluster size

java - Spring Data MongoRepository save(T) 不工作......有时

java - MongoDB:查询子文档:Java

hadoop - Combiner 实现和内部工作

java - 如何在 Spring Data MongoDB 中投影 $strLenCP

javascript - 根据用户个人资料中的数组在集合中查找

node.js - 在 Node 中对 mongodb 客户端 findOne() 进行排序

mongodb - Spring Data Mongodb 事务期间如何使用文档锁来防止外部修改记录

java - Spring Reactive Web 更新方法创建一条新记录而不是更新现有记录