Това е нещо, което просто не може да се направи с рамката за агрегиране и единственият текущ метод на MongoDB, наличен за този тип операции, е mapReduce.
Причината е, че рамката за агрегиране няма начин да се позовава на друг документ в процес на подготовка освен настоящия. Това всъщност се отнася и за етапите на "групиране" на тръбопровода, тъй като въпреки че нещата са групирани по "ключ", не можете наистина да се справите с отделни документи по начина, по който искате.
MapReduce от друга страна има една налична функция, която ви позволява да правите това, което искате тук, и дори не е „пряко“ свързана с агрегацията. Всъщност това е способността да има "променливи с глобален обхват" на всички етапи. И наличието на „променлива“, която да „съхранява последния документ“ е всичко, от което се нуждаете, за да постигнете резултата.
Така че това е доста прост код и всъщност не е необходимо „намаляване“:
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 }
}
)
Което ви дава резултат, подобен на този:
{
"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
}
Това наистина е просто избиране на „нещо уникално“ като излъчен _id
стойност, а не нещо конкретно, защото всичко, което наистина прави, е разликата между стойностите на различни документи.
Глобалните променливи обикновено са решението за тези типове "сдвояване" на агрегации или създаване на "текущи суми". В момента рамката за агрегиране няма достъп до глобални променливи, въпреки че може да е хубаво да има това. Рамката mapReduce ги има, така че вероятно е справедливо да се каже, че те трябва да бъдат достъпни и за рамката за агрегиране.
В момента обаче не са, така че се придържайте към mapReduce.