2015-12-06 236 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 }