MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Funzione MapReduce in MongoDB - Raggruppamento di documenti per ID

Nel tuo apprendimento potresti aver perso la pagina del manuale principale su mapReduce . C'è un pezzo vitale di informazioni che hai perso o non hai letto e appreso:

E poi un po' dopo:

Quindi ciò che sostanzialmente significa è che poiché il "riduttore" in realtà non elabora "tutte" le chiavi univoche tutte in una volta, si aspetta lo stesso "input" che fornisce "output", poiché quell'output può essere reinserito in di nuovo il riduttore.

Per lo stesso motivo il "mapper" deve emettere esattamente ciò che ci si aspetta come uscita "riduttore", che è anche l'"ingresso" del riduttore. Quindi in realtà non "modifichi" affatto la struttura dei dati, ma la "riduci" semplicemente.

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"}     
)

Ora stai gestendo l'input come un array che è anche l'output, quindi vengono restituiti i risultati attesi.

La prossima cosa da imparare è che nella maggior parte casi mapReduce non è proprio quello che vuoi usare e dovresti usare quadro di aggregazione invece.

A differenza di mapReduce, utilizza operatori "codificati in modo nativo" e non richiede l'interpretazione di JavaScript per l'esecuzione. E ciò significa in gran parte che è "più veloce" e spesso molto più semplice nella costruzione.

Ecco la stessa operazione con .aggregate() :

db.Cool.aggregate([
    { "$group": {
        "_id": "$id",
        "cools": { "$push": "$cool" }
    }}
])

Stessa cosa, meno codifica e molto più veloce.

Per l'output su un'altra raccolta utilizzi $out :

db.Cool.aggregate([
    { "$group": {
        "_id": "$id",
        "cools": { "$push": "$cool" }
    }},
    { "$out": "reduced" }
])

Per la cronaca, ecco l'output di mapReduce:

{ "_id" : "a", "value" : { "cools" : [ "a1", "a2" ] } }
{ "_id" : "b", "value" : { "cools" : [ "b1", "b2" ] } }
{ "_id" : "c", "value" : { "cools" : [ "c1" ] } }
{ "_id" : "d", "value" : { "cools" : [ "d1" ] } }

E la produzione aggregata. Con l'unica differenza dalla mapReduce _id e value l'output obbligatorio è che le chiavi sono invertite, poiché $group non garantisce un ordine (ma è generalmente osservato come uno stack inverso):

{ "_id" : "d", "cools" : [ "d1" ] }
{ "_id" : "c", "cools" : [ "c1" ] }
{ "_id" : "b", "cools" : [ "b1", "b2" ] }
{ "_id" : "a", "cools" : [ "a1", "a2" ] }