2015-12-06 184 views
1

萨姆数组元素我有c阵列下列集合中的每个文件MongoDB中聚合

{ 
    { 
    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} ] 
    } 
} 

parentIdc每个子文档内的内部是包含文件的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 
    } 
}); 

回答

3

您需要首先$group文档的“类型”中,使用$sum累加器操作返回的“K”的总和,并使用其返回的$push二维数组“c”。现在您需要两个"$unwind"阶段,在该阶段将“c”2D阵列非规格化。在管道中的最后一个阶段是另一个$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 } 

Starting in version 3.2,以前仅在$group阶段可用的以下累加器表达式现在也可用于$project阶段。

这意味着我们可以利用它并使用$sum累加器运算符$project。当然,$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 }