MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Como posso selecionar um número de registros por um campo específico usando o mongodb?


Você ainda não pode fazer isso usando a estrutura de agregação - você pode obter o valor $max ou data superior para cada grupo, mas a estrutura de agregação ainda não tem uma maneira de acumular os N principais e não há como enviar todo o documento para o conjunto de resultados (somente campos individuais).

Então você tem que recorrer ao MapReduce. Aqui está algo que funcionaria, mas tenho certeza de que existem muitas variantes (todas exigem de alguma forma classificar uma matriz de objetos com base em um atributo específico, peguei emprestada minha solução de um dos as respostas nesta pergunta .

Função Map - exibe o nome do grupo como uma chave e todo o restante do documento como o valor - mas o exibe como um documento contendo um array porque tentaremos acumular um array de resultados por grupo:
map = function () { 
    emit(this.name, {a:[this]}); 
}

A função reduce irá acumular todos os documentos pertencentes ao mesmo grupo em um array (via concat). Observe que, se você otimizar o reduce para manter apenas os cinco principais elementos do array verificando a data, não precisará da função finalize e usará menos memória durante a execução do mapreduce (também será mais rápido).
reduce = function (key, values) {
    result={a:[]};
    values.forEach( function(v) {
        result.a = v.a.concat(result.a);
    } );
    return result;
}

Como estou mantendo todos os valores para cada chave, preciso de uma função finalize para extrair apenas os últimos cinco elementos por chave.
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 um documento de modelo semelhante ao que você forneceu, você executa isso chamando o 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 tem _id como nome do grupo e valores como matriz dos cinco documentos mais recentes da coleção para esse nome de grupo.