我有很多文件:
{
_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
,我不确定这样做的最佳方法。
答案 0 :(得分:4)
尝试运行以下聚合管道:
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
}
请注意,文档{ value: 'yellow', count: '12'}
的计数值是一个字符串,在聚合中它将打折为0值,因为 $sum
运算符有效地聚合数值,否则字符串值将累积为零默认值。
在$group
管道中,您现在通过$colors.value
字段对展平的颜色数组文档进行分组,然后使用累加器在分组的文档上返回所需的聚合。累加器运算符 $first
用于此分组操作,因为当文档按定义的顺序时,它会从每个组的第一个文档返回一个值,在这种情况下,您希望返回将所有文档分组时的形状字段。这是维护管道中文档顺序的一个技巧。
这里需要注意的一点是,在执行管道时,MongoDB会将运营商相互管道化。 "管"这里采用Linux的含义:运算符的输出成为以下运算符的输入。每个运算符的结果是一个新的文档集合。所以Mongo按如下方式执行上一个管道:
collection | $unwind | $group | $unwind | $group => result
因此, $first
是获取上一个管道到下一个管道的形状字段所必需的。
答案 1 :(得分: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}
}
}
]
);