我在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 }
}
},
]);
但是基于那个星期以及之前的几个星期来达到这个总和是非常棘手的。
答案 0 :(得分: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;
});
关于这是否需要在服务器或客户端上发生,最重要的是它。但是由于聚合pipline没有这样的"全局",所以你可能不应该在没有输出到另一个集合的情况下进行任何进一步的处理。