我有一个数据集如下:
{
item: '123',
array: [{
array2:[{
array3: [{
property1: 1234
}]
}],
anotherArray: [{
property2: 1234
}]
}]
}
我试图在同一个请求中汇总property2和property one的总和。 这是我目前的聚合函数:
Item.aggregate([
{$match: {itemId: 1234}},
{$unwind: "$array"},
{$unwind: "$array.array2"},
{$unwind: "$array.array2.array3"},
{$unwind: "$array.anotherArray"},
{$group: {
_id: 0,
property1: {$sum: '$array.array2.array3.property1'},
property2: {$sum: '$array.anotherArray.property2'}
}},
{$project: {
_id: 0,
property1: "$property1",
property2: "$property2",
}},
], function (err, aggregate) {
callback(null, aggregate);
});
问题是属性1和2的聚合结果总是它们应该是的两倍。
我猜问题是“sunArray”的$ unwind,因为当我删除它时,我得到了正确的聚合值。
是否可以使用一个聚合函数在多个数组上进行聚合?
目前我只是使用异步并行向db发出2个不同的请求,但是我想在未来进行更复杂的聚合而不需要额外的db调用。
答案 0 :(得分:2)
如上所述,结构不是很好,应该根据其意图进行审查。它真的不清楚为什么它如此结构化,或者在任何一种情况下阵列中的任何其他内容都会弄乱结果。
但是当文档中有多个数组时,有一种通用的方法,基本上是分别处理每个数组并获得#34;总数"首先是每个文件。然后总结所有文件中的总数:
Item.aggregate([
// Unwind only 1 inner array first
{ "$unwind": "$array" },
{ "$unwind": "$array.array2" },
{ "$unwind": "$array.array2.array3" },
// Group back the sum of the element and the first of the other array
// and only per document
{ "$group": {
"_id": "$_id",
"property1": { "$sum": "$array.array2.array3.property1" },
"anotherArray": { "$first": "$array.anotherArray" }
}},
// Unwind the other array
{ "$unwind": "$anotherArray" },
// Group back the total and the first summed per document
{ "$group": {
"_id": "$_id",
"property1": { "$first": "$property1" },
"property2": { "$sum": "$anotherArray.property2" }
}},
// Total all documents and output
{ "$group": {
"_id": null,
"property1": { "$sum": "$property1" },
"property2": { "$sum": "$property2" },
}},
{ "$project": {
"_id": 0,
"property1": 1,
"property2": 1
}}
],callback);
因此,通过一次仅包含一个数组并且仅在原始文档中获取总计,可以避免为另一个数组的每个展开项创建多个副本的重复问题。使用离散文档总计,可以很容易地从所需的选择中获得总计。
答案 1 :(得分:0)
最后,我找到了一个使用MongoDB $ setUnion的用例的解决方案。
以下是我用于问题的代码:
Item.aggregate([
{$match: { itemID: '1234'}},
{$unwind: "$array1"},
{$unwind: "$array1.array2"},
{$project: {
_id: 0,
combined: {$setUnion: ['$array1.anotherArray', '$array1.array2.array3']},
}},
{$unwind: "$combined"},
{$group: {
_id: 0,
property1: {$sum: '$combined.property1'},
property2: {$sum: '$combined.property2'}
}},
], function (err, aggregate) {
cb(aggregate);
});