Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to sum the value of a key across all documents in a MongoDB collection

Tags:

mongodb

nosql

I have collection in MongoDB:

{ "_id" : ObjectId("4d2407265ff08824e3000001"), "subida" : 3.95 } { "_id" : ObjectId("4d2551b4ae9fa739640df821"), "subida" : 6.03 } { "_id" : ObjectId("4d255b115ff08821c2000001"), "subida" : 5.53 } { "_id" : ObjectId("4d25e8d55ff08814f8000001"), "subida" : 1.96 } 

How I can sum the value of a key, e.g., "subida", across all documents? With the documents above, I should receive something along the lines of:

{ "subida" : 17.47 } 
like image 834
JAM Avatar asked Jan 06 '11 23:01

JAM


People also ask

How can I find the value of an array of objects in MongoDB?

To search the array of object in MongoDB, you can use $elemMatch operator. This operator allows us to search for more than one component from an array object.

How do you sum in mongoose?

Aggregation in MongoDB provides a vast range of very useful operators. One such operator is $sum. As the name suggests, the $sum operator is used to get the sum of numerical values. It is commonly used with $match and $group.

What does find () do in MongoDB?

Find() Method. In MongoDB, find() method is used to select documents in a collection and return a cursor to the selected documents.

What does $sum do in MongoDB?

Calculates and returns the collective sum of numeric values.


2 Answers

In this case, aggregation is much simpler and much more efficient than mapReduce:

db.collection.aggregate({     $group: {         _id: '',         subida: { $sum: '$subida' }     }  }, {     $project: {         _id: 0,         subida: '$subida'     } }) 
  1. use $group with $sum to calculate sum
  2. use projection's $project operator to remove id key required by $group operator
like image 133
Ilya Builuk Avatar answered Sep 18 '22 07:09

Ilya Builuk


I'd personally perform a mapreduce on the collection :

map is a simple function emitting the "subida" field. The key should the same if you need a single sum; the result after reduce will yield the single object {<key>: <sum>}, with <key> being whatever value you supplied in the emit.

map = function() { emit(<key>, this.subida); } 

reduce is also a simple function summing them :

red = function(k, v) {   var i, sum = 0;   for (i in v) {     sum += v[i];   }   return sum; } 

You can then call mapreduce on your collection <mycollection>:

res = db.<mycollection>.mapReduce(map, red); 

Which will create a temporary new collection you can manipulate like any other collection. The value returned by mapReduce holds several values regarding the mapReduce such as the time taken, status..., as well as the temp. collection name created in the "result" field. To get the values you need, you have to query that collection :

db[res.result].find() 

Which should give you the object {<key>: <sum>}.

If you run MongoDB 1.7.4 or higher, you can save you a bit of hassle by asking MongoDB to return the result directly without creating a collection :

db.<mycollection>.mapReduce(map, red, {out : {inline: 1}}); 
like image 39
Yochiro Avatar answered Sep 22 '22 07:09

Yochiro