Question

How can I run aggregate, min, max, sum and friends on embedded docs?

For example:

Get the average cost of ALL events that a district has, where they are pretty deeply embedded.

District.schools.all.events.all.costs.avg(:value)

Obviously doesn't work.

District.avg('schools.events.costs.value')

Neither does that. It gives this error message:

Mongo::OperationFailure: Database command 'group' failed: (errmsg: 'exception: reduce
invoke failed: JS Error: TypeError: obj.schools 
has no properties reduce setup:1'; code:   '9010'; ok: '0.0').

So is it possible or do I need to write my own map/reduce functions?

Was it helpful?

Solution

Yes, MapReduce would work. You could also use cursors to process a query result. Like:

min = 99999999;
max = -99999999;
sum = 0;
count = 0
db.School.find({}).forEach(function(s) {
    if (s.first.events.first.cost < min)
        min = s.first.events.first.cost;
    if (s.first.events.first.cost > max)
        max = s.first.events.first.cost;
    sum += s.first.events.first.cost;
    ++count;
});

You now have the min and max and can calculate the average and mean from the sum and count.

Mongodb does not have the ability to calculate the aggregate functions in its query language directly. Actually, that statement is not entirely true, since there is the count() function to count the number of results returned by a query, and there is the group() function. But the group function is a lot like a MapReduce, and cannot be used on sharded databases. If you are interested in the group function, see: http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Group

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top