一个请求中有多个聚合函数

我有一个数据集是这样的:

{ item: '123', array: [{ array2:[{ array3: [{ property1: 1234 }] }], anotherArray: [{ property2: 1234 }] }] } 

我试图在同一个请求中聚合property2和property之和。 这是我目前的聚合函数:

 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,因为当我删除它,我得到正确的聚合值。

是否有可能使用一个聚合函数在多个数组上进行聚合?

目前我只是使用asynchronous并行方式向数据库发出两个不同的请求,但是我希望将来可以进行更复杂的聚合,而不需要额外的数据库调用。

如上所述,结构不是一个好的结构,应该对其意图进行审查。 这真的不清楚,为什么它是如此结构化,或者在这两种情况下,如果在这种情况下任何其他的东西可能会混淆在这里的结果。

但是在文档中有多个数组时,有一个通用的方法,那就是基本上分别对待每个数组,并首先获得每个文档的“总计”。 然后总结所有文件的总数:

 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); 

因此,通过一次仅包含一个数组并仅在原始文档中获取总计,您可避免为其他数组的每个展开项创build多个副本的重复问题。 随着离散的文件总数,它是很容易得到你所需的select总的总数。

最后,我find了一个MongoDB $ setUnion用例的解决scheme。

这里是我用于我的问题的代码:

 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); });