sql >> Databáze >  >> NoSQL >> MongoDB

Jak mohu vybrat počet záznamů na konkrétní pole pomocí mongodb?

Pomocí agregačního rámce to zatím nemůžete udělat - můžete získat hodnotu $max nebo nejvyšší datum pro každou skupinu, ale agregační rámec zatím nemá způsob, jak akumulovat top N a navíc neexistuje způsob, jak vložit celý dokument do sady výsledků (pouze jednotlivá pole).

Takže se musíte vrátit k MapReduce. Tady je něco, co by fungovalo, ale jsem si jistý, že existuje mnoho variant (všechny vyžadují nějak seřadit pole objektů na základě konkrétního atributu, své řešení jsem si vypůjčil od jednoho z odpovědi v této otázce .

Funkce Map – vypíše název skupiny jako klíč a celý zbytek dokumentu jako hodnotu – ale vypíše jej jako dokument obsahující pole, protože se pokusíme shromáždit pole výsledků za skupinu:

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

Funkce snížení shromáždí všechny dokumenty patřící do stejné skupiny do jednoho pole (přes concat). Všimněte si, že pokud optimalizujete redukci tak, aby se zachovalo pouze prvních pět prvků pole kontrolou data, nebudete potřebovat funkci finalizace a během spuštění mapreduce spotřebujete méně paměti (také to bude rychlejší).

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

Vzhledem k tomu, že uchovávám všechny hodnoty pro každý klíč, potřebuji funkci finalizace, která vytáhne pouze posledních pět prvků na klíč.

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

Pomocí dokumentu šablony podobného tomu, který jste poskytli, jej spustíte voláním příkazu 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,
}

Každý výsledek má _id jako název skupiny a hodnoty jako pole posledních pěti dokumentů z kolekce pro daný název skupiny.



  1. (MongoDB Compass) vyhledávání pomocí let nefunguje

  2. Jak provést jednorázovou synchronizaci DB s jinou DB v MongoDB?

  3. MongoDB vnořené ověření dokumentu pro dílčí dokumenty

  4. MongoDB dotaz:$blízko s agregací