MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Fonction MapReduce dans MongoDB - Regroupement de documents par ID

Dans votre apprentissage, vous avez peut-être manqué la page de manuel de base sur mapReduce . Il y a une pièce essentielle d'informations que vous avez manquées ou que vous n'avez pas lues et apprises :

Et puis un peu après :

Donc, ce que cela signifie essentiellement, c'est que parce que le "réducteur" ne traite pas réellement "toutes" les clés uniques en même temps, il attend alors la même "entrée" qu'il donne la "sortie", puisque cette sortie peut être réinjectée dans le réducteur à nouveau.

Pour la même raison, le "mappeur" doit produire exactement ce qui est attendu comme sortie du "réducteur", qui est également l'"entrée" du réducteur. Ainsi, vous ne "modifiez" pas du tout la structure des données, mais vous la "réduisez" simplement à la place.

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

Maintenant, vous gérez l'entrée comme un tableau qui est également la sortie, puis les résultats attendus sont renvoyés.

La prochaine chose à apprendre est que dans la plupart cas mapReduce n'est pas vraiment ce que vous voulez utiliser, et que vous devriez utiliser le cadre d'agrégation à la place.

Contrairement à mapReduce, cela utilise des opérateurs "codés nativement" et n'a pas besoin d'interprétation JavaScript pour s'exécuter. Et cela signifie en grande partie qu'il est "plus rapide" et souvent beaucoup plus simple dans sa construction.

Voici la même opération avec .aggregate() :

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

Même chose, moins de codage et beaucoup plus rapide.

Sortie vers une autre collection que vous utilisez $out :

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

Pour mémoire, voici la sortie de mapReduce :

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

Et la production globale. Avec la seule différence avec le mapReduce _id et value la sortie obligatoire étant que les clés sont inversées, puisque $group ne garantit pas un ordre ( mais est généralement observé comme une pile inversée ):

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