需要进行数据聚合,汇总根表和子表中的数据
有这样的输入数据
[
{
id: ID,
points: 10,
sources: [{
sourceId: 's1',
sourcePoints: 6,
},
{
sourceId: 's2',
sourcePoints: 4,
}]
},
{
id: ID,
points: 2,
sources: [{
sourceId: 's1',
sourcePoints: 2,
}]
}
];
我想要这份总结
{
id: ID,
points: 12 // sum
sources: {
s1: { sourcePoints: 8 } // sum of all s1 from all records for sourceId = s1 and id = ID
s2: { sourcePoints: 4 } // same as above, for sourceId = s2 and id = ID
... // sources can be N
}
}
从根获取总和对我来说很简单
[
{ $match: { id: ID } },
{ $group: { _id: $id, sum: { $sum: '$points' }} }
]
但我不知道如何从数组中添加总和
$arrayToObject
运算符,因为您可能有 N 个名称未知的源。
一种解决方案如下:
db.collection.aggregate([
{
$match: {
id: "ID"
}
},
{
"$unwind": "$sources"
},
{
$group: {
_id: {
mainId: "$id",
"sourceId": "$sources.sourceId"
},
sumPerSoureId: {
$sum: "$sources.sourcePoints"
}
}
},
{
$group: {
_id: "$_id.mainId",
totalPoints: {
$sum: "$sumPerSoureId"
},
keyVal: {
$push: {
"k": "$_id.sourceId",
"v": {
"sourcePoints": "$sumPerSoureId"
}
}
}
}
},
{
$project: {
_id: 0,
id: "$_id",
points: "$totalPoints",
sources: {
"$arrayToObject": "$keyVal"
}
}
}
])
提供的解决方案可能无法针对数百万个文档进行优化,因为我使用了两个
$unwind
开始。