Skip to content

Instantly share code, notes, and snippets.

@vquaiato
Created May 24, 2012 15:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save vquaiato/2782117 to your computer and use it in GitHub Desktop.
Save vquaiato/2782117 to your computer and use it in GitHub Desktop.
Map/Reduce no MongoDB

###Collections Salas{_id} Reservas{_id, sala_id, data}

###Preciso contar as reservas de cada sala por uma data:

map = function () {
    emit(this.sala_id, [1]);
}
reduce = function (sala, values) {
    var sum = 0;
    if (values) {
        for (var i = 0; i < values.length; i++) {
            sum += 1;
        }
    }
    return {sala:sala, total:sum};
}
db.reservas.mapReduce(map, reduce, {"out":"resultado"})

###Problema: Quando existe apenas 1 reserva para uma sala, o reduce não é chamado:

db.resultado.find({})
{ "_id" : ObjectId("4fbd6d5b700f6e1266000002"), "value" : [ 1 ] }
{ "_id" : ObjectId("4fbd6e69700f6e1266000004"), "value" : { "sala" : ObjectId("4fbd6e69700f6e1266000004"), "total" : 2 } }
@vquaiato
Copy link
Author

Aparentemente resuolvi usando uma function finalize:

finalize = function(key, values){
    var total = 1;
    if(!values.length)
        total = values;
        
    return total;
}

E passei isso no runCommad:

db.runCommand({mapreduce: "reservas", map: map, reduce: reduce, out:"foo", finalize: finalize})

E no resultado:

> db.foo.find({})
{ "_id" : ObjectId("4fbd6d5b700f6e1266000002"), "value" : 1 }
{ "_id" : ObjectId("4fbd6e69700f6e1266000004"), "value" : 2 }

Desta forma quando o reduce não for chamado no finalize eu trato tudo.

PS: ao invés de passar um [1] no emit estou passando apenas 1. Assim elimino o if no finalize.
PPS: se eu não precisar formatar a saída, então nem preciso do finalize. A saída que eu estava usando {sala: foo, total: bar} é a mesma que o próprio map/reduce já me retorna {key: foo, value: bar}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment