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

Unire due raccolte in MongoDB

È simile a una domanda che è stata posta su MongoDB-users Google Gruppi.
https://groups.google.com/group/mongodb-user/browse_thread/thread/60a8b683e2626ada?pli=1

La risposta fa riferimento a un tutorial in linea simile al tuo esempio:http://tebros.com/2011/07/using-mongodb-mapreduce-to-join-2-collections/

Per ulteriori informazioni su MapReduce in MongoDB, consultare la documentazione:http://www.mongodb.org/display/DOCS/MapReduce

Inoltre, è disponibile un'utile guida dettagliata su come funziona un'operazione MapReduce nella sezione "Extra" dell'articolo MongoDB Cookbook intitolato "Trovare valori massimi e minimi con documenti con versione":http://cookbook.mongodb. org/patterns/finding_max_and_min/

Perdonami se hai già letto alcuni dei documenti di riferimento. Li ho inclusi a beneficio di altri utenti che potrebbero leggere questo post e nuovi nell'utilizzo di MapReduce in MongoDB

È importante che gli output delle istruzioni 'emit' nelle funzioni Mappa corrispondano agli output della funzione Riduci. Se è presente un solo documento di output dalla funzione Mappa, la funzione Riduci potrebbe non essere eseguita affatto e quindi la raccolta di output avrà documenti non corrispondenti.

Ho leggermente modificato le istruzioni della tua mappa per emettere documenti nel formato dell'output desiderato, con due array di "classi" separati.
Ho anche rielaborato la tua istruzione reduce per aggiungere nuove classi agli array classi_1 e classi_2, solo se non esistono già.

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

L'esecuzione delle due operazioni MapReduce risulta nella raccolta seguente, che corrisponde al formato desiderato:

> 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 emette sempre documenti nella forma di {_id:"id", value:"value"}Sono disponibili ulteriori informazioni sull'utilizzo dei documenti secondari nel documento intitolato "Dot Notation (Reaching into Objects)":http:/ /www.mongodb.org/display/DOCS/Dot+Notation+%28Raggiungere+in+oggetti%29

Se desideri che l'output di MapReduce appaia in un formato diverso, dovrai farlo a livello di codice nella tua applicazione.

Si spera che questo migliorerà la tua comprensione di MapReduce e ti avvicinerà di un passo alla produzione della raccolta di output desiderata. Buona fortuna!