sql >> Base de Datos >  >> NoSQL >> MongoDB

Fusionando dos colecciones en MongoDB

Esto es similar a una pregunta que se hizo en los grupos de Google de usuarios de MongoDB.
https://groups.google.com/group/mongodb-user/browse_thread/thread/60a8b683e2626ada?pli=1

La respuesta hace referencia a un tutorial en línea que se parece a su ejemplo:http://tebros.com/2011/07/using-mongodb-mapreduce-to-join-2-collections/

Para obtener más información sobre MapReduce en MongoDB, consulte la documentación:http://www.mongodb.org/display/DOCS/MapReduce

Además, hay un tutorial paso a paso útil sobre cómo funciona una operación de MapReduce en la sección "Extras" del artículo del libro de recetas de MongoDB titulado "Encontrar valores máximos y mínimos con documentos versionados":http://cookbook.mongodb. org/patterns/finding_max_and_min/

Perdóname si ya has leído algunos de los documentos a los que se hace referencia. Los he incluido para el beneficio de otros usuarios que pueden estar leyendo esta publicación y que son nuevos en el uso de MapReduce en MongoDB

Es importante que los resultados de las instrucciones 'emit' en las funciones Map coincidan con los resultados de la función Reduce. Si solo hay una salida de documento por la función Map, es posible que la función Reducir no se ejecute en absoluto, y luego su colección de salida tendrá documentos que no coinciden.

Modifiqué ligeramente sus declaraciones de mapa para emitir documentos en el formato de su salida deseada, con dos matrices de "clases" separadas.
También modifiqué su declaración de reducción para agregar nuevas clases a las matrices de clases_1 y clases_2, solo si ya no existen.

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

Ejecutar las dos operaciones de MapReduce da como resultado la siguiente colección, que coincide con el formato deseado:

> 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 siempre genera documentos en forma de {_id:"id", value:"value"}Hay más información disponible sobre cómo trabajar con subdocumentos en el documento titulado "Notación de puntos (alcanzar objetos)":http:/ /www.mongodb.org/display/DOCS/Dot+Notation+%28Reaching+into+Objects%29

Si desea que la salida de MapReduce aparezca en un formato diferente, tendrá que hacerlo mediante programación en su aplicación.

Con suerte, esto mejorará su comprensión de MapReduce y lo acercará un paso más a la producción de la colección de salida deseada. ¡Buena suerte!