MongoDB中聚合总和数组元素 [英] Sum array elements in Mongodb aggregation
问题描述
我有以下类集c
阵列中的每个文件里面
{
{
ID:1,
K:2.2,
类型:狗,
C:[{parentId的:1,P:2.2},{parentId的:1,P:1.4}]
}, {
ID:2,
K:4.3,
类型:猫,
C:[{parentId的:2,P:5.2},{parentId的:2,P:4.5}]
}
}
parentId的
在每个子ç
里面是包含文件的ID。
我要组由所有文档中键入
各组所知道的总和 K
和所有的总和 p
在该组的所有阵列。
目前我做的在
P
的小组赛阶段,但累加氏/ code>的总和,在应用程序的结果数组中。我想要做的 P
的总和,在DB!
这是我目前做的:
db.myCol.aggregate([{
$组:{
_id:{类型:'$类型},
K:{$总和:'$ K'} //总和的k值,非常方便!
//号码:{$总和:'$ c.0.p'}< ====不行的,太
C:{$ addToSet:'$ C'} //添加到每个群组的成员的所有C数组
}
}
],功能(ERR,RES){
//去了C-阵列和求和的p值
变种ACCP = 0; //累加器P值
对于(VAR I = 0; I< res.length;我++){
变种C = RES [I] .C;
对于(VAR J = 0; J< c.length; J ++){
VAR C2 = C [J]。
对于(VAR K = 0; K< c2.length; k ++){//终于到对象数组c
ACCP + = C2 [K] .P;
}
}
RES [I] .C = ACCP; //使用累积的p值代替阵列
}
});
您需要先的 $组
文档按型,使用的 $金额
累加器操作符返回的总和K并使用 $推
它返回的C的二维数组。现在,你需要两个$放松阶段,你非规范化的C二维数组。在管道中的最后一个阶段是另一个 $组
在那里你计算p的总和使用点号的阶段。
db.collection.aggregate([
{'$组:{
'_id':'$类型',
'K':{'$总和':'$ K'},C:{$推':'$ C'}
}},
{'$开卷':'$ C'},
{'$开卷':'$ C'},
{'$组:{
'_id':'$ _id',
'K':{'$第一':'$ K'},
C:{$总和':'$ c.p'}
}}
])
其中产量:
{_id:狗,K:2.2,C:3.6}
{_id:猫,K:4.3,C:9.7}
在3.2版本开始,下面的蓄能器前pressions,previously只有
$组中可用
的阶段,现在在$项目还提供
阶段。
块引用>这意味着我们可以利用这一点,并使用
$金额
蓄能器运营商的$项目
。当然,$地图
运算符返回P为每个文档的数组。db.collection.aggregate([
{'$工程:{
类型:1,
'K':1,
'C': {
'$总和:{
'$图:{
'输入':'$ C',
作为':'SUBC',
在':'$$ subc.p
}
}
}
}},
{'$组:{
'_id':'$类型',
'K':{'$总和':'$ K'},
C:{$总和':'$ C'}
}}
])将返回:
{_id:猫,K:4.3,C:9.7}
{_id:狗,K:2.2,C:3.6}I have the following collection with
c
array inside each document{ { 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} ] } }
parentId
inside each subdocument inc
is id of containing document.I want to group all docs by
type
and in each group know sum ofk
and sum of allp
in all arrays of the group.Currently I do summation of
k
in the group stage but summation ofp
in the result array in the application. I want to do summation ofp
in DB!This is what I do currently:
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 } });
解决方案You need to first
$group
your documents by "type", use the$sum
accumulator operator to return the sum of "k" and use the$push
which returns a 2D array of "c". Now you need two "$unwind" stage where you denormalize the "c" 2D array. Your last stage in the pipeline is another$group
stage where you calculate the sum of "p" using "dot notation"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' } }} ])
Which yields:
{ "_id" : "dog", "k" : 2.2, "c" : 3.6 } { "_id" : "cat", "k" : 4.3, "c" : 9.7 }
Starting in version 3.2, the following accumulator expressions, previously only available in the
$group
stage, are now also available in the$project
stage.Which means that we can take advantage of that and use the
$sum
accumulator operator in$project
. Of course the$map
operator returns an array of "p" for each document.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' } }} ])
Which returns:
{ "_id" : "cat", "k" : 4.3, "c" : 9.7 } { "_id" : "dog", "k" : 2.2, "c" : 3.6 }
这篇关于MongoDB中聚合总和数组元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!