MongoDB中聚合总和数组元素 [英] Sum array elements in Mongodb aggregation

查看:197
本文介绍了MongoDB中聚合总和数组元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下类集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 in c is id of containing document.

I want to group all docs by type and in each group know sum of k and sum of all p in all arrays of the group.

Currently I do summation of k in the group stage but summation of p in the result array in the application. I want to do summation of p 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆