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

Seskupování dokumentů do dvojic pomocí mongo agregace

To je něco, co prostě nelze udělat s agregačním rámcem a jedinou současnou metodou MongoDB dostupnou pro tento typ operace je mapReduce.

Důvodem je to, že agregační rámec nemá žádný způsob, jak odkazovat na jakýkoli jiný dokument v procesu, než je tento. To ve skutečnosti platí i pro fáze „seskupení“ kanálu, protože i když jsou věci seskupeny na „klíč“, nemůžete ve skutečnosti s jednotlivými dokumenty nakládat tak, jak byste chtěli.

MapReduce má na druhou stranu k dispozici jednu funkci, která vám zde umožňuje dělat, co chcete, a ani to „přímo“ nesouvisí s agregací. Je to ve skutečnosti schopnost mít „globálně uspořádané proměnné“ ve všech fázích. A mít "proměnnou" pro v podstatě "uložení posledního dokumentu" je vše, co potřebujete k dosažení svého výsledku.

Takže je to docela jednoduchý kód a ve skutečnosti není vyžadována žádná "redukce":

db.collection.mapReduce(
    function () {
      if (lastVal != null)
        emit( this._id, this.val - lastVal );
      lastVal = this.val;
    },
    function() {}, // mapper is not called
    {
        "scope": { "lastVal": null },
        "out": { "inline": 1 }
    }
)

Což vám dává výsledek podobný tomuto:

{
    "results" : [
            {
                    "_id" : ObjectId("54a425a99b8bcd6f73e2d662"),
                    "value" : 2
            },
            {
                    "_id" : ObjectId("54a425a99b8bcd6f73e2d663"),
                    "value" : 3
            },
            {
                    "_id" : ObjectId("54a425a99b8bcd6f73e2d664"),
                    "value" : 4
            }
    ],
    "timeMillis" : 3,
    "counts" : {
            "input" : 4,
            "emit" : 3,
            "reduce" : 0,
            "output" : 3
    },
    "ok" : 1
}

To je opravdu jen výběr "něčeho jedinečného" jako emitovaného _id hodnotu spíše než cokoli konkrétního, protože to jediné, co ve skutečnosti dělá, je rozdíl mezi hodnotami v různých dokumentech.

Globální proměnné jsou obvykle řešením těchto typů „párování“ agregací nebo vytváření „průběžných součtů“. Právě teď agregační rámec nemá přístup ke globálním proměnným, i když by to mohlo být hezké mít. Framework mapReduce je má, takže je pravděpodobně spravedlivé říci, že by měly být dostupné i pro agregační rámec.

Právě teď však nejsou, takže zůstaňte u mapReduce.




  1. mongoose - metoda 'save' neexistuje

  2. Jak zacházet se zastaralými připojeními v MongoDB

  3. Porozumění Meteor Publish / Subscribe

  4. Jak si Redis Streams poradí s využitím veškeré dostupné paměti?