Reputation: 2429
I have two documents like this
{ "_id" : ObjectId("552cd26276b783ed66031cc4"), "vals" : [ 2, 3, 4, 5 ] }
{ "_id" : ObjectId("552cd26e76b783ed66031cc5"), "vals" : [ 1, 2, 3, 4 ] }
I need aggregated sum of this two lists
expected output:
[3, 5, 7, 9]
i.e [2+1, 3+2, 4+3, 5+4]
I'm not even sure if this is possible in MongoDB. Any light on this?
Upvotes: 9
Views: 2258
Reputation: 2868
Just for an update. This is possible in aggregation framework in the upcoming release of mongoDB 3.2. They have added a new feature to get the unwind index of array in $unwind stage of mongoDB aggregation called includeArrayIndex.
Using this feature you can use aggregate query of the form:
db.collection.aggregate(
{$unwind: { path: "$vals", includeArrayIndex: "arrayIndex" }},
{$group: { '_id': '$arrayIndex', sum : {$sum: '$vals'}}},
{$sort: { '_id': 1 }},
{$group : { '_id': null, valSum: {$push: '$sum'}}}
)
Explanation:
Output:
{ '_id': null, valSum: [3, 5, 7, 9] }
The main advantage of this approach is that, you need not have arrays of same length. Also it can take any number of input documents. Thanks to the includeArrayIndex feature.
Cheers!
Upvotes: 2
Reputation: 755
Aggregation framework is not just the aggregation pipeline.
Of course you can also use map reduce with really simple functions:
var map_function = function(){
for(var i=0;i<this.vals.length;i++){
emit(i,this.vals[i]);
}
}
var reduce_function = function(key, values){
return Array.sum(values)
}
The output is a list of documents where the _id
is the index and the value
is the sum. Like this:
[{u'_id': 0.0, u'value': 3.0},
{u'_id': 1.0, u'value': 5.0},
{u'_id': 2.0, u'value': 7.0},
{u'_id': 3.0, u'value': 9.0}]
Upvotes: -1
Reputation: 1069
Sorry I didn't answer the question correctly. I was thinking of how to sum each object's array. Not adding the arrays between the two objects.
(edit above)
I am new to this but I think you want to use the aggregate operator $unwind, which will explode the array then $sum the "vals". It should look like this
db.Test.aggregate([{$unwind:"$vals"},{$group:{_id:"$_id","TotalVals":{$sum:"$vals"}}}])
refer to the operators here http://docs.mongodb.org/manual/reference/operator/aggregation-group/
This ($unwind) will create one document for each value in the array so watch your memory for bigger collections. This ($unwind) is done in Memory I believe.
Upvotes: 0