我有一个数据集如下:
{
item: '123',
array: [{
array2:[{
array3: [{
property1: 1234
}]
}],
anotherArray: [{
property2: 1234
}]
}]
}
我正在尝试在同一请求中聚合属性 2 和属性 1 的总和。 这是我当前的聚合函数:
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);
});
问题在于,属性一和属性二的合计结果始终是应有值的两倍。
我猜问题出在“anotherArray”的 $unwind 上,因为当我删除它时,我得到了正确的聚合值。
是否可以使用一个聚合函数对多个数组进行聚合?
目前,我只是使用异步并行方式向数据库发出 2 个不同的请求,但我想在将来进行更复杂的聚合,而无需进行额外的数据库调用。
最佳答案
如前所述,该结构不是一个好的结构,可能应该对其意图进行审查。确实不清楚为什么它是这样结构化的,或者在任何一种情况下数组中的其他内容是否会弄乱这里的结果。
但是,当文档中有多个数组时,有一种通用方法,基本上是单独处理每个数组,并首先获取每个文档的“总计”。然后将所有文档的总数相加:
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);
因此,通过一次仅包含一个数组并仅在原始文档中获取总计,您可以避免为另一个数组的每个展开项目创建多个副本的重复问题。通过离散文档总计,可以轻松地从所需选择中获取总体总计。
关于node.js - 一个请求中的多个聚合函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29124585/