MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Zusammenführen von zwei Sammlungen in MongoDB

Dies ähnelt einer Frage, die in Google Groups von MongoDB-Benutzern gestellt wurde.
https://groups.google.com/group/mongodb-user/browse_thread/thread/60a8b683e2626ada?pli=1

Die Antwort verweist auf ein Online-Tutorial, das Ihrem Beispiel ähnlich sieht:http://tebros.com/2011/07/using-mongodb-mapreduce-to-join-2-collections/

Weitere Informationen zu MapReduce in MongoDB finden Sie in der Dokumentation:http://www.mongodb.org/display/DOCS/MapReduce

Darüber hinaus gibt es im Abschnitt „Extras“ des MongoDB Cookbook-Artikels mit dem Titel „Finding Max And Min Values ​​with Versioned Documents“ eine nützliche Schritt-für-Schritt-Anleitung zur Funktionsweise einer MapReduce-Operation:http://cookbook.mongodb. org/patterns/finding_max_and_min/

Verzeihen Sie mir, wenn Sie einige der genannten Dokumente bereits gelesen haben. Ich habe sie zum Nutzen anderer Benutzer eingefügt, die diesen Beitrag möglicherweise lesen und neu in der Verwendung von MapReduce in MongoDB sind

Es ist wichtig, dass die Ausgaben der 'emit'-Anweisungen in den Map-Funktionen mit den Ausgaben der Reduce-Funktion übereinstimmen. Wenn nur ein Dokument von der Map-Funktion ausgegeben wird, wird die Reduce-Funktion möglicherweise überhaupt nicht ausgeführt, und Ihre Ausgabesammlung weist dann nicht übereinstimmende Dokumente auf.

Ich habe Ihre map-Anweisungen leicht modifiziert, um Dokumente im Format Ihrer gewünschten Ausgabe auszugeben, mit zwei getrennten "classes"-Arrays.
Ich habe auch Ihre Reduce-Anweisung überarbeitet, um neue Klassen zu den Klassen-1- und Klassen-2-Arrays hinzuzufügen, nur wenn sie existieren noch nicht.

var mapDetails = function(){
    var output = {studentid: this.studentid, classes_1: [], classes_2: [], year: this.year, overall: 0, subscore: 0}
    if (this.year == 1) {
        output.classes_1 = this.classes;
    }
    if (this.year == 2) {
        output.classes_2 = this.classes;
    }
    emit(this.studentid, output);
};

var mapGpas = function() {
    emit(this.studentid, {studentid: this.studentid, classes_1: [], classes_2: [], year: 0, overall: this.overall, subscore: this.subscore});
};

var r = function(key, values) {
    var outs = { studentid: "0", classes_1: [], classes_2: [], overall: 0, subscore: 0};

    values.forEach(function(v){
        outs.studentid = v.studentid;
        v.classes_1.forEach(function(class){if(outs.classes_1.indexOf(class)==-1){outs.classes_1.push(class)}})
        v.classes_2.forEach(function(class){if(outs.classes_2.indexOf(class)==-1){outs.classes_2.push(class)}})

        if (v.year == 0) {
            outs.overall = v.overall;
            outs.subscore = v.subscore;
        }
    });
    return outs;
};

res = db.details.mapReduce(mapDetails, r, {out: {reduce: 'joined'}})
res = db.gpas.mapReduce(mapGpas, r, {out: {reduce: 'joined'}})

Das Ausführen der beiden MapReduce-Operationen führt zu der folgenden Sammlung, die Ihrem gewünschten Format entspricht:

> db.joined.find()
{ "_id" : "12345a", "value" : { "studentid" : "12345a", "classes_1" : [ 1, 17, 19, 21 ], "classes_2" : [ 32, 91, 101, 217 ], "overall" : 97, "subscore" : 1 } }
{ "_id" : "24680a", "value" : { "studentid" : "24680a", "classes_1" : [ 1, 11, 18, 22 ], "classes_2" : [ ], "overall" : 76, "subscore" : 2 } }
{ "_id" : "98765a", "value" : { "studentid" : "98765a", "classes_1" : [ 2, 12, 19, 22 ], "classes_2" : [ 32, 99, 110, 215 ], "overall" : 85, "subscore" : 5 } }
>

MapReduce gibt Dokumente immer in Form von {_id:"id", value:"value"}aus. Weitere Informationen zum Arbeiten mit Unterdokumenten finden Sie im Dokument "Dot Notation (Reaching into Objects)":http:/ /www.mongodb.org/display/DOCS/Dot+Notation+%28Reaching+into+Objects%29

Wenn Sie möchten, dass die Ausgabe von MapReduce in einem anderen Format angezeigt wird, müssen Sie dies programmgesteuert in Ihrer Anwendung tun.

Hoffentlich wird dies Ihr Verständnis von MapReduce verbessern und Sie der Produktion Ihrer gewünschten Ausgabesammlung einen Schritt näher bringen. Viel Glück!