http://blog.knoldus.com/2013/02/03/joins-now-possible-in-mongodb/

MongoDB incorporó en su version 1.8 (van por la 2.4) soporte MapReduce, una funcionalidad muy interesante para el caso en el que hayamos decidido modelar con referencias (ver link).

Con las características MapReduce se pueden hacer pre-joins de 2 colecciones (si no es necesario realizar 2 queries).

La mejor forma de entender lo que se puede hacer es ver un ejemplo:

1. Creo las colecciones employee y department:

db.createCollection("employee");

db.createCollection("department");

2. Guardo datos en la colección employee:

db.employee.insert(

{

_id: 1,

name: { first: ‘John’, last: ‘Backus’ },

city: ‘New York’,

department:1

}

);

db.employee.insert(

{

_id: 2,

name: { first: ‘Merry’, last: ‘Desuja’ },

city: ‘London’,

department:2

}

);

3. Guardo datos en la colección department:

db.department.insert(

{

_id: 1,

department: ‘Manager’

}

);

db.department.insert(

{

_id: 2,

department: ‘Accountant’

}

);

4. Creo la función map en Javascript, esta función emite pares (clave,valor) para cada documento de entrada:

var map = function () {

var output= {firstname:this.name.first, lastname:this.name.last , department:db.department.findOne({_id:this.department}).department}

emit(this._id, output);

};

5. Creo la función reduce en Javascript que acepta dos argumentos: clave y valores:

var reduce = function(key, values) {

var outs={ firstname:null , lastname:null , department:null}

values.forEach(function(v){

if(outs.firstname ==null){

outs.firstname = v.firstname

}

if(outs.lastname ==null){

outs.lastname = v.lastname

}

if(outs.department ==null){

outs.department = v.department

}

});

return outs;

};

6. Ejecuto el comando mapReduce para lanzar esta operación:

db.employee.mapReduce(map,reduce,{out: 'emp_dept'});

El resultado se almacena en la variable emp_dept, que almacena:

{ "_id" : 1, "value" : { "firstname" : "John", "lastname" : "Backus", "department" : "Manager" } }

{ "_id" : 2, "value" : { "firstname" : "Merry", "lastname" : "Desuja", "department" : "Accountant" } }