2016-03-01 63 views
2

我的文檔巨大的一堆這樣:蒙戈總結:總和計數數組重複值田間

{ 
    _id: '1', 
    colors: [ 
    { value: 'red', count: 2 }, 
    { value: 'blue', count: 3} 
    ] 
    shapes: [ 
    { value: 'cube', type: '3d' }, 
    { value: 'square', type: '2d'} 
    ] 
},  
{ 
    _id: '2', 
    colors: [ 
    { value: 'red', count: 7 }, 
    { value: 'blue', count: 34}, 
    { value: 'yellow', count: 12} 
    ] 
    shapes: [ 
    { value: 'prism', type: '3d' }, 
    { value: 'triangle', type: '2d'} 
    ] 
} 

通過使用$unwind$addToSet,因爲這樣的:

db.getCollection('coll').aggregate([{$unwind:"$colors"},{$unwind:"$shapes"},{$group:{_id:null,colors:{$addToSet:"$colors"},shapes:{$addToSet:"$shapes"}]) 

我能得到如下:

{ 
    "_id" : null, 
    "colors" : [ 
     { "value" : "red", "count" : 2 }, 
     { "value" : "blue", "count" : 3 }, 
     { "value" : "red", "count" : 7 }, 
     { "value" : "blue", "count" : 34 }, 
     { "value" : "yellow", "count" : 12 } 
    ] 
    "shapes" : [ 
     { value: 'cube', type: '3d' }, 
     { value: 'square', type: '2d'} 
     { value: 'prism', type: '3d' }, 
     { value: 'triangle', type: '2d'} 
    ] 
} 

然而我想要的是判斷重複的唯一的領域「值」,並總結「計數」字段重複,即

{ 
    "_id" : null, 
    "colors" : [ 
     { "value" : "red", "count" : 9 }, 
     { "value" : "blue", "count" : 37 }, 
     { "value" : "yellow", "count" : 12 } 
    ] 
    "shapes" : [ 
     { value: 'cube', type: '3d' }, 
     { value: 'square', type: '2d'} 
     { value: 'prism', type: '3d' }, 
     { value: 'triangle', type: '2d'} 
    ] 
} 

question表明我可以使用$colors.value作爲_id字段和$sum與總的count。然而,因爲我有第二個數組$unwind和聚合/ $group,我不確定最好的方式去做這件事。

回答

3

嘗試運行以下聚合管道:

pipeline = [ 
    {"$unwind": "$colors"}, 
    { 
     "$group": { 
      "_id": "$colors.value", 
      "count": { "$sum": "$colors.count" }, 
      "shapes": { "$first": "$shapes" } 
     } 
    }, 
    {"$unwind": "$shapes"}, 
    { 
     "$group": { 
      "_id": null, 
      "colors": { 
       "$addToSet": { 
        "value": "$_id", 
        "count": "$count" 
       } 
      }, 
      "shapes": { "$addToSet": "$shapes" }    
     } 
    } 
]; 
db.getCollection('coll').aggregate(pipeline) 

樣本輸出

{ 
    "result" : [ 
     { 
      "_id" : null, 
      "colors" : [ 
       { 
        "value" : "red", 
        "count" : 9 
       }, 
       { 
        "value" : "blue", 
        "count" : 37 
       }, 
       { 
        "value" : "yellow", 
        "count" : 12 
       } 
      ], 
      "shapes" : [ 
       { 
        "value" : "square", 
        "type" : "2d" 
       }, 
       { 
        "value" : "cube", 
        "type" : "3d" 
       }, 
       { 
        "value" : "triangle", 
        "type" : "2d" 
       }, 
       { 
        "value" : "prism", 
        "type" : "3d" 
       } 
      ] 
     } 
    ], 
    "ok" : 1 
} 

注意文件的計數值是一個字符串,在聚合中它將被打折爲0,因爲$sum運算符有效地聚合數值,否則字符串值會被累計爲零默認值。


裏面$group管道,你現在通過$colors.value場分組扁平的顏色排列的文件,然後使用蓄能器返回的分組文件所需的聚集。累積器運算符$first用於此分組操作,因爲它在文檔處於已定義順序時爲每個組返回第一個文檔的值,在這種情況下,您希望返回形狀字段,因爲當所有文檔都是分組。維護管道內文檔的順序更是一種竅門。

在這裏需要注意的一件事是執行一個管道時,MongoDB將管道操作符互相管道。這裏的「管道」採用Linux的含義:操作員的輸出成爲後面的操作員的輸入。每個操作員的結果都是一個新的文檔集合。所以蒙戈執行以前的管道如下:

collection | $unwind | $group | $unwind | $group => result 

因此$first有必要從以前的管道輸送到下一個獲得形狀領域。

+0

這看起來不錯。讓我試試看!我也編輯了我的帖子,以刪除錯誤的撇號-_-錯字嘉豪!非常感謝! :) @chridam – Tacocat

+0

呃,你能向我解釋這是什麼嗎?:'「shapes」:{「$ first」:「$ shapes」}'我可能在誤解之下運作..:3 – Tacocat

+1

@Tacocat增加了一些解釋,希望你能理解它在管道中的使用。在這裏它使用了更多的機制來獲取前一個管道中的'shapes'字段到分組中,而不影響當前的聚合。 – chridam

0

所以,你需要重寫你的插入,或將字符串轉換爲計數值的整數。

這裏是插入:

db.so.insert([{ 
    _id: '1', 
    colors: [ 
    { value: 'red', count: 2 }, 
    { value: 'blue', count: 3} 
    ] 
},  
{ 
    _id: '2', 
    colors: [ 
    { value: 'red', count: 7 }, 
    { value: 'blue', count: 34}, 
    { value: 'yellow', count: 12} 
    ] 
}]); 

要做到現有表的轉換,可以look at this SO

然後你就可以做一個簡單的兩個步驟彙總查詢:

db.so.aggregate(
    [ 
    { 
     $unwind: "$colors" 
    }, 
    { 
     $group: { 
     _id : { color : "$colors.value"}, 
     count : { $sum: "$colors.count"}, 
     simple : { $sum: 1} 
     } 
    } 
    ] 
); 
+0

我已編輯我的帖子擺脫撇號。那些是錯別字。不幸的是,這實際上並不能回答我的問題。我知道我可以使用'$ colors.value'作爲'_id'。然而,這裏的問題是我希望保留和彙總我的'形狀'領域,我不確定實現這一點的最佳方式是什麼,@Nicolas Modrzyk – Tacocat