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.