Reputation: 10516
Consider this set of docs:
[
{_id:1, values:[1, 2, 3]},
{_id:2, values:[4, 5, 6]}
]
Is there any elegant way to group/sum the arrays into a new array, where the nth element is the sum of the nth elements of the original documents?
{_id:null, values:[5, 7, 9]}
I can sum up specific elements in an aggregation step:
{$group:{
_id:null,
Values0: {$sum:{$arrayElemAt:["$values",0]}},
Values1: {$sum:{$arrayElemAt:["$values",1]}},
Values2: {$sum:{$arrayElemAt:["$values",2]}}
}},
But I can't get these back into an array. Also something that would require less typing would be highly appreciated :). If this doesn't work I can loop over the bson docs in C# and construct the answer that way but would prefer something in an aggregation pipeline (or mapreduce maybe? Haven't looked into that yet)
Upvotes: 1
Views: 269
Reputation: 49945
You can use $group to get an array of arrays and then use $reduce to process that array. Using $range you can generate indexes that can be used to get each item of both arrays (result and currently processed item). Value at index zero will be an initialValue
for $reduce
and values at indexes 1...size
will be added to the result in every iteration.
db.collection.aggregate([
{
$group: {
_id: null,
values : {
$push: "$values"
}
}
},
{
$project: {
result: {
$reduce: {
input: { $slice: [ "$values", 1, { $size: "$values" } ] },
initialValue: { $arrayElemAt: [ "$values", 0 ] },
in: {
$map: {
input: { $range: [ 0, { $size: "$$this" } ] },
as: "index",
in: {
$add: [
{ $arrayElemAt: [ "$$this", "$$index" ] },
{ $arrayElemAt: [ "$$value", "$$index" ] }
]
}
}
}
}
}
}
}
])
Upvotes: 1