Dit is iets dat gewoon niet kan met het aggregatieraamwerk, en de enige huidige MongoDB-methode die beschikbaar is voor dit type bewerking is mapReduce.
De reden hiervoor is dat het aggregatieraamwerk op geen enkele manier kan verwijzen naar een ander document in de pijplijn dan het huidige. Dit is eigenlijk ook van toepassing op het "groeperen" van pijplijnfasen, aangezien hoewel dingen op een "sleutel" zijn gegroepeerd, u niet echt met individuele documenten kunt omgaan zoals u dat wilt.
MapReduce daarentegen heeft één functie beschikbaar waarmee je hier kunt doen wat je wilt, en het is niet eens "direct" gerelateerd aan aggregatie. Het is in feite de mogelijkheid om "globaal bereikbare variabelen" in alle stadia te hebben. En het hebben van een "variabele" om in feite "het laatste document op te slaan" is alles wat je nodig hebt om je resultaat te bereiken.
Het is dus een vrij eenvoudige code, en er is in feite geen "reductie" vereist:
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 }
}
)
Dat geeft je een resultaat dat ongeveer zo is:
{
"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
}
Dat is eigenlijk gewoon "iets unieks" kiezen als de uitgezonden _id
waarde in plaats van iets specifieks, want het enige wat dit werkelijk doet is het verschil tussen waarden op verschillende documenten.
Globale variabelen zijn meestal de oplossing voor dit soort "paren"-aggregaties of het produceren van "lopende totalen". Op dit moment heeft het aggregatieraamwerk geen toegang tot globale variabelen, ook al is het misschien leuk om dit te hebben. Het mapReduce-framework heeft ze, dus het is waarschijnlijk eerlijk om te zeggen dat ze ook beschikbaar zouden moeten zijn voor het aggregatieframework.
Op dit moment zijn ze dat echter niet, dus blijf bij mapReduce.