2016-03-01 95 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