Wednesday, 15 July 2015

mongodb - How to get sum of child entries for hierarchical documents? -



mongodb - How to get sum of child entries for hierarchical documents? -

i have document of next form:

class="lang-js prettyprint-override">{ "name": "root1", "children": [{ "name": "a", "children": [{ "name": "a1", "items": 20 }, { "name": "a2", "items": 19 }], "items": 8 }, { "name": "b", "items": 12 }], "items": 1 }

that is, each level has "name" field, "items" field, , optionally children field. run query returns total number of items each root. in example, should homecoming (since 20+19+8+12+1=60)

class="lang-js prettyprint-override">{ "_id" : "root1", "items" : 60 }

however, each document can have arbitrarily many levels. is, illustration has 2 3 children below root, other documents may have more. is, cannot like

class="lang-js prettyprint-override">db.mycollection.aggregate( { $unwind : "$children" }, { $group : { _id : "$name", items: { $sum : "$items" } } } )

what sort of query work?

there no way descend arrays arbitrary depths using aggregation framework. sort of construction need utilize mapreduce can programatically this:

class="lang-js prettyprint-override">db.collection.mapreduce( function () { var items = 0; var action = function(current) { items += current.items; if ( current.hasownproperty("children") ) { current.children.foreach(function(child) { action( kid ); }); } }; action( ); emit( this.name, items ); }, function(){}, { "out": { "inline": 1 } } )

if not want mapreduce consider construction info , things differently:

class="lang-js prettyprint-override">{ "name": "root1", "items": 1, "path": [], "root": null }, { "name": "a", "items": 8, "path": ["root1"], "root": "root1" }, { "name": "a1", "items": 20, "path": ["root1", "a"], "root": "root1" }, { "name": "a2", "items": 19, "path": ["root1", "a"], "root": "root1" }, { "name": "b", "items": 12, "path": ["root1"], "root": "root1" }

then have simple aggregate:

class="lang-js prettyprint-override">db.collection.aggregate([ { "$group": { "_id": { "$cond": [ "$root", "$root", "$name" ] }, "items": { "$sum": "$items" } }} ])

so if take different approach mapping hierarchy doing things such aggregating totals paths much easier without recursive inspection otherwise required.

the approach need depends on actual usage requirements.

mongodb mapreduce mongodb-query aggregation-framework

No comments:

Post a Comment