Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fastest way to get the average of a specific field in MongoDB

Let's say I have a dataset like the following:

{ "_id" : ObjectId("4dd51c0a3f42cc01ab0e6506"), "views" : 1000, "status" : 1 }
{ "_id" : ObjectId("4dd51c0e3f42cc01ab0e6507"), "views" : 2000, "status" : 1 }
{ "_id" : ObjectId("4dd51c113f42cc01ab0e6508"), "views" : 3000, "status" : 1 }
{ "_id" : ObjectId("4dd51c113f42cc01ab0e6508"), "views" : 4000, "status" : 0 }

What is the fastest way (performance-wise) to get the average number of views for all documents with a status of 1? Is Map/Reduce required for something basic like this, or is there another way?

like image 796
James Simpson Avatar asked Jun 20 '11 16:06

James Simpson


People also ask

Which is faster in find and aggregate in MongoDB?

The aggregation query takes ~80ms while the find query takes 0 or 1ms.

How does MongoDB calculate average cost?

We can manually verify this is correct by calculating the average of the points values by hand: Average of Points: (30 + 30 + 20 + 25 + 25) / 5 = 26.

Which is faster find or aggregate?

Aggregation wins where the volume of data returned is much less than the original data or where you don't have the skill to build fast client side aggregations. I hope it answers your query.


2 Answers

Use group: http://www.mongodb.org/display/DOCS/Aggregation

you need a counter for the documents and another for the sum of views. In finalize you just do a division on these two numbers.

db.test.group(
   { cond: {"status": 1}
   , initial: {count: 0, total:0}
   , reduce: function(doc, out){ out.count++; out.total += doc.views }
   , finalize: function(out){ out.avg = out.total / out.count }
} );
like image 69
Karoly Horvath Avatar answered Oct 20 '22 00:10

Karoly Horvath


Faster way to get average in any case - precalculate it(probably you can do this in background) and create extra field/collection to store it.

like image 29
Andrew Orsich Avatar answered Oct 20 '22 00:10

Andrew Orsich