MongoDB Map Reduce

MongoDB mapReduce() method can be used to aggregate documents in a MongoDB Collection.

In this tutorial – MongoDB Map Reduce, we shall learn to use mapReduce() function for performing aggregation operations on a MongoDB Collection, with the help of examples.

Syntax of Mongo mapReduce()

Following is the syntax of mapReduce() function that could be used in Mongo Shell

> db.collection.mapReduce(
   function() {emit(key,value);},  // map function
   function(key,values) {return reduceFunction},  // reduce function
   { out: collection }
)

Example 1 – MongoDB mapReduce()

In this example we shall take school db in which students is a collection and the collection has documents where each document has name of the student, marks he/she scored in a particular subject. We shall apply mapReduce function to accumulate the marks for each student.

Following is the students collection.

> db.students.find({});
{ "_id" : ObjectId("5a1f9ce431c157f3ec2aec39"), "name" : "Midhu", "subject" : "science", "marks" : 68 }
{ "_id" : ObjectId("5a1f9ce431c157f3ec2aec3a"), "name" : "Midhu", "subject" : "maths", "marks" : 98 }
{ "_id" : ObjectId("5a1f9ce431c157f3ec2aec3b"), "name" : "Midhu", "subject" : "sports", "marks" : 77 }
{ "_id" : ObjectId("5a1f9ce431c157f3ec2aec3c"), "name" : "Akhil", "subject" : "science", "marks" : 67 }
{ "_id" : ObjectId("5a1f9ce431c157f3ec2aec3d"), "name" : "Akhil", "subject" : "maths", "marks" : 87 }
{ "_id" : ObjectId("5a1f9ce431c157f3ec2aec3e"), "name" : "Akhil", "subject" : "sports", "marks" : 89 }
{ "_id" : ObjectId("5a1f9ce431c157f3ec2aec3f"), "name" : "Anish", "subject" : "science", "marks" : 67 }
{ "_id" : ObjectId("5a1f9ce431c157f3ec2aec40"), "name" : "Anish", "subject" : "maths", "marks" : 78 }
{ "_id" : ObjectId("5a1f9ce431c157f3ec2aec41"), "name" : "Anish", "subject" : "sports", "marks" : 90 }

mapReduce() In Mongo Shell

Following is a step by step guide to prepare mapReduce function for the use case in Mongo Shell :

1. Prepare Map function

Our map function should emit key-value pair. And in this case, name is key and value is marks.

</>
Copy
var map = function() {emit(this.name,this.marks);};

2. Prepare Reduce function

Our map function should emit key-value pair. And in this case, name is key and value is marks.

</>
Copy
var reduce = function(name,marks) {return Array.sum(marks);};

3. Prepare mapReduce function

Our map function should emit key-value pair. And in this case, name is key and value is marks.

</>
Copy
db.students.mapReduce(
   map,
   reduce,
   {  out: "totals" }
);

out: “totals”  : the output is written to totals collection in the same database.

4. Start Mongo Daemon

Run the following command in terminal to start mongo daemon.

  ~$ sudo mongod --port 27017 --dbpath /var/lib/mongodb

Now Mongo Daemon would be waiting for connections on port 27017.

5. Run mapReduce

Start a Mongo Shell and Run the above commands (in Step 1 to Step 3) in Mongo Shell.

> var map = function() {emit(this.name,this.marks);};
> var reduce = function(name,marks) {return Array.sum(marks);};
> db.students.mapReduce(
...    map,
...    reduce,
...    {  out: "totals" }
... );
{
	"result" : "totals",
	"timeMillis" : 599,
	"counts" : {
		"input" : 9,
		"emit" : 9,
		"reduce" : 3,
		"output" : 3
	},
	"ok" : 1
}
> db.totals.find({})
{ "_id" : "Akhil", "value" : 243 }
{ "_id" : "Anish", "value" : 235 }
{ "_id" : "Midhu", "value" : 243 }

The value has been accumulated (aggregated) for the key values and the output is written to totals collection.

Using mapReduce Command in Mongo Script

Following is the Mongo Script file that runs mapReduce command and writes result to totals collection.

mongo-mapreduce-example.js

</>
Copy
// equivalent for "use <db>" command in mongo shell
db = db.getSiblingDB('school')

db.runCommand( {
    mapReduce: "students",
    map: function() {
        emit( this.name, this.marks );
    },
    reduce: function(name, values) {
        var value = 0;
        for (var index = 0; index < values.length; ++index) {
            value += values[index];
        }
        return value;
    },
    out: {
        replace: "totals"
    }
} )

Run the JavaScript file using mongo command

~$ mongo mongo-mapreduce-example.js 
MongoDB shell version v3.4.10
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.10

You may check the totals collection

> db.totals.find({})
{ "_id" : "Akhil", "value" : 243 }
{ "_id" : "Anish", "value" : 235 }
{ "_id" : "Midhu", "value" : 243 }

You may choose any property as a key or value from the collection for the mapReduce() function.

Conclusion

In this MongoDB Tutorial, we have learnt how to use MongoDB MapReduce function in Mongo Shell and Mongo Script with examples.