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

¿Cómo puedo seleccionar una cantidad de registros por un campo específico usando mongodb?

Todavía no puede hacer esto utilizando el marco de agregación:puede obtener el valor máximo de $ o la fecha máxima para cada grupo, pero el marco de agregación aún no tiene una forma de acumular los N principales, además, no hay forma de insertar todo el documento en el conjunto de resultados. (solo campos individuales).

Así que tienes que recurrir a MapReduce. Aquí hay algo que funcionaría, pero estoy seguro de que hay muchas variantes (todas requieren ordenar de alguna manera una matriz de objetos según un atributo específico, tomé prestada mi solución de uno de las respuestas en esta pregunta .

Función de mapa:genera el nombre del grupo como clave y el resto del documento como valor, pero lo genera como un documento que contiene una matriz porque intentaremos acumular una matriz de resultados por grupo:

map = function () { 
    emit(this.name, {a:[this]}); 
}

La función de reducción acumulará todos los documentos pertenecientes al mismo grupo en una matriz (a través de concat). Tenga en cuenta que si optimiza reduce para mantener solo los cinco elementos principales de la matriz al verificar la fecha, entonces no necesitará la función de finalización y usará menos memoria durante la ejecución de mapreduce (también será más rápido).

reduce = function (key, values) {
    result={a:[]};
    values.forEach( function(v) {
        result.a = v.a.concat(result.a);
    } );
    return result;
}

Dado que mantengo todos los valores para cada clave, necesito una función de finalización para extraer solo los últimos cinco elementos por clave.

final = function (key, value) {
      Array.prototype.sortByProp = function(p){
       return this.sort(function(a,b){
       return (a[p] < b[p]) ? 1 : (a[p] > b[p]) ? -1 : 0;
      });
    }

    value.a.sortByProp('date');
    return value.a.slice(0,5);
}

Usando un documento de plantilla similar al que proporcionó, ejecute esto llamando al comando mapReduce:

> db.top5.mapReduce(map, reduce, {finalize:final, out:{inline:1}})
{
    "results" : [
        {
            "_id" : "group1",
            "value" : [
                {
                    "_id" : ObjectId("516f011fbfd3e39f184cfe13"),
                    "name" : "group1",
                    "date" : ISODate("2013-04-17T20:07:59.498Z"),
                    "contents" : 0.23778377776034176
                },
                {
                    "_id" : ObjectId("516f011fbfd3e39f184cfe0e"),
                    "name" : "group1",
                    "date" : ISODate("2013-04-17T20:07:59.467Z"),
                    "contents" : 0.4434165076818317
                },
                {
                    "_id" : ObjectId("516f011fbfd3e39f184cfe09"),
                    "name" : "group1",
                    "date" : ISODate("2013-04-17T20:07:59.436Z"),
                    "contents" : 0.5935856597498059
                },
                {
                    "_id" : ObjectId("516f011fbfd3e39f184cfe04"),
                    "name" : "group1",
                    "date" : ISODate("2013-04-17T20:07:59.405Z"),
                    "contents" : 0.3912118375301361
                },
                {
                    "_id" : ObjectId("516f011fbfd3e39f184cfdff"),
                    "name" : "group1",
                    "date" : ISODate("2013-04-17T20:07:59.372Z"),
                    "contents" : 0.221651989268139
                }
            ]
        },
        {
            "_id" : "group2",
            "value" : [
                {
                    "_id" : ObjectId("516f011fbfd3e39f184cfe14"),
                    "name" : "group2",
                    "date" : ISODate("2013-04-17T20:07:59.504Z"),
                    "contents" : 0.019611883210018277
                },
                {
                    "_id" : ObjectId("516f011fbfd3e39f184cfe0f"),
                    "name" : "group2",
                    "date" : ISODate("2013-04-17T20:07:59.473Z"),
                    "contents" : 0.5670706110540777
                },
                {
                    "_id" : ObjectId("516f011fbfd3e39f184cfe0a"),
                    "name" : "group2",
                    "date" : ISODate("2013-04-17T20:07:59.442Z"),
                    "contents" : 0.893193120136857
                },
                {
                    "_id" : ObjectId("516f011fbfd3e39f184cfe05"),
                    "name" : "group2",
                    "date" : ISODate("2013-04-17T20:07:59.411Z"),
                    "contents" : 0.9496864483226091
                },
                {
                    "_id" : ObjectId("516f011fbfd3e39f184cfe00"),
                    "name" : "group2",
                    "date" : ISODate("2013-04-17T20:07:59.378Z"),
                    "contents" : 0.013748752186074853
                }
            ]
        },
        {
            "_id" : "group3",
                        ...
                }
            ]
        }
    ],
    "timeMillis" : 15,
    "counts" : {
        "input" : 80,
        "emit" : 80,
        "reduce" : 5,
        "output" : 5
    },
    "ok" : 1,
}

Cada resultado tiene _id como nombre de grupo y valores como matriz de los cinco documentos más recientes de la colección para ese nombre de grupo.