MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Função MapReduce no MongoDB - Agrupando documento por ID


Em seu aprendizado, você pode ter perdido a página principal do manual em mapReduce . Existe uma peça vital de informações que você perdeu ou não leu e aprendeu:

E um pouco depois disso:

Então, o que isso basicamente significa é que, como o "redutor" não processa "todas" as chaves exclusivas de uma só vez, ele espera a mesma "entrada" que fornece "saída", uma vez que essa saída pode ser realimentada em o redutor novamente.

Pela mesma razão, o "mapeador" precisa produzir exatamente o que é esperado como a saída do "redutor", que também é a "entrada" do redutor. Portanto, você não "altera" a estrutura de dados, mas apenas a "reduz".
db.Cool.mapReduce(
    function(){emit(this.id, { "cools": [this.cool] })},
    function(key, values){
        var res = [];
        values.forEach(function(cool){
            cool.cools.forEach(function(v) {
                res.push(v);
            });
        });
        return {cools: res};
    },
    {out: "MapReduce"}     
)

Agora você está manipulando a entrada como um array que também é a saída, então os resultados esperados são retornados.

A próxima coisa a aprender é que na maioria casos mapReduce não é realmente o que você quer usar, e que você deveria estar usando o estrutura de agregação em vez de.

Ao contrário de mapReduce, ele usa operadores "codificados nativamente" e não precisa de interpretação de JavaScript para ser executado. E isso significa em grande parte que é "mais rápido" e muitas vezes muito mais simples na construção.

Aqui está a mesma operação com .aggregate() :
db.Cool.aggregate([
    { "$group": {
        "_id": "$id",
        "cools": { "$push": "$cool" }
    }}
])

Mesma coisa, menos codificação e muito mais rápido.

Ao enviar para outra coleção, você usa $out :
db.Cool.aggregate([
    { "$group": {
        "_id": "$id",
        "cools": { "$push": "$cool" }
    }},
    { "$out": "reduced" }
])

Para o registro, aqui está a saída mapReduce:
{ "_id" : "a", "value" : { "cools" : [ "a1", "a2" ] } }
{ "_id" : "b", "value" : { "cools" : [ "b1", "b2" ] } }
{ "_id" : "c", "value" : { "cools" : [ "c1" ] } }
{ "_id" : "d", "value" : { "cools" : [ "d1" ] } }

E a produção agregada. Com a única diferença do mapReduce _id e value saída obrigatória sendo que as chaves estão invertidas, pois $group não garante um pedido (mas geralmente é observado como uma pilha reversa):
{ "_id" : "d", "cools" : [ "d1" ] }
{ "_id" : "c", "cools" : [ "c1" ] }
{ "_id" : "b", "cools" : [ "b1", "b2" ] }
{ "_id" : "a", "cools" : [ "a1", "a2" ] }