Mongodb: Aggregation : sum up values in an array before $group -
i have collection of documents following structure:
{ _id: 1, array: [ {value: 10 }, {value: 11 }, {value: 12 } ] }
i want make aggregate query on collection: proportion of each item. (i.e. example proportion of item 1 value
of item 1 divided sum of values of 3 items.
note: want within single query.
the basic idea here $unwind
array, $group
document , apply each array member. works better mongodb 2.6 or greater due $map
operator:
db.collection.aggregate([ { "$unwind": "$array" }, { "$group": { "_id": "$_id", "array": { "$push": "$array" }, "total": { "$sum": "$array.value" } }}, { "$project": { "array": { "$map": { "input": "$array", "as": "el", "in": { "value": "$$el.value", "prop": { "$divide": [ "$$el.value", "$total" ] } } } } }} ])
or earlier versions:
db.collection.aggregate([ { "$unwind": "$array" }, { "$group": { "_id": "$_id", "array": { "$push": "$array" }, "total": { "$sum": "$array.value" } }}, { "$unwind": "$array" }, { "$group": { "_id": "$_id", "array": { "$push": { "value": "$array.value", "prop": { "$divide": [ "$array.value", "$total" ] } } } }} ])
in either case, if not "aggregating" beyond document, far more efficient calculation in client code. $unwind
here can costly due does.
also if stored "total" element, simple $project
need, comes @ little cost itself. keeping total on updates simple usage of $inc
operator $push
new elements array.
Comments
Post a Comment