[英]Sum array elements in Mongodb aggregation
我在每个文档中都有以下带有c
数组的集合
{
{
id: 1,
k: 2.2,
type: "dog",
c: [ {parentId:1, p:2.2}, {parentId:1, p:1.4} ]
},
{
id: 2,
k: 4.3,
type:"cat",
c: [ {parentId:2, p:5.2}, {parentId:2, p:4.5} ]
}
}
c
每个子文档中的parentId
是包含文档的id。
我想按type
对所有文档进行分组,并且在每个组中知道组的所有数组中k
总和和所有p
总和。
目前我在组阶段对k
进行求和,但在应用程序的结果数组中对p
进行求和。 我想在DB中p
进行求和!
这就是我目前所做的事情:
db.myCol.aggregate([
{
$group: {
_id: { type: '$type'},
k: {$sum: '$k'}, // sum k values, very easy!
// p: {$sum: '$c.0.p'} <==== Does not work, too
c: {$addToSet: '$c'} // add to each group all c arrays of group's members
}
}
], function(err, res) {
// go over c-arrays and sum p values
var accP = 0; // accumulator for p values
for ( var i=0; i<res.length; i++ ) {
var c = res[i].c;
for (var j=0;j<c.length; j++) {
var c2 = c[j];
for ( var k=0; k<c2.length; k++) { // finally got to objects c array
accP += c2[k].p;
}
}
res[i].c = accP; // replace array with accumulated p value
}
});
您需要首先按“类型”对文档进行$group
,使用$sum
accumulator运算符返回“k”的总和,并使用$push
返回“c”的2D数组。 现在你需要两个“$ unwind”阶段,你可以对“c”二维数组进行反规范化。 您在管道中的最后一个阶段是另一个$group
阶段,您可以使用“点符号”计算“p”的总和
db.collection.aggregate([
{ '$group': {
'_id': '$type',
'k': { '$sum': '$k' }, 'c': { '$push': '$c' }
} },
{ '$unwind': '$c' },
{ '$unwind': '$c' },
{ '$group': {
'_id': '$_id',
'k': { '$first': '$k' },
'c': { '$sum': '$c.p' }
}}
])
产量:
{ "_id" : "dog", "k" : 2.2, "c" : 3.6 }
{ "_id" : "cat", "k" : 4.3, "c" : 9.7 }
从版本3.2开始 ,以前只在
$group
阶段中可用的累加器表达式现在也可以在$project
阶段中使用。
这意味着我们可以利用它并在$project
使用$sum
accumulator运算符。 当然$map
运算符为每个文档返回一个“p”数组。
db.collection.aggregate([
{ '$project': {
'type': 1,
'k': 1,
'c': {
'$sum': {
'$map': {
'input': '$c',
'as': 'subc',
'in': '$$subc.p'
}
}
}
}},
{ '$group': {
'_id': '$type',
'k': { '$sum': '$k' },
'c': { '$sum': '$c' }
}}
])
哪个回报:
{ "_id" : "cat", "k" : 4.3, "c" : 9.7 }
{ "_id" : "dog", "k" : 2.2, "c" : 3.6 }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.