Du kan ikke gøre dette ved at bruge aggregeringsrammen endnu - du kan få $max- eller topdatoværdien for hver gruppe, men aggregeringsrammerne har endnu ikke en måde at akkumulere top N, og der er ingen måde at skubbe hele dokumentet ind i resultatsættet (kun individuelle felter).
Så du skal falde tilbage på MapReduce. Her er noget, der ville fungere, men jeg er sikker på, at der er mange varianter (alle kræver på en eller anden måde sortering af en række objekter baseret på en specifik attribut, jeg lånte min løsning fra en af svarene i dette spørgsmål .
Kortfunktion - udlæser gruppenavn som en nøgle og hele resten af dokumentet som værdi - men den udlæser det som et dokument, der indeholder en matrix, fordi vi vil forsøge at akkumulere en matrix af resultater pr. gruppe:
map = function () {
emit(this.name, {a:[this]});
}
Reduceringsfunktionen vil akkumulere alle dokumenter, der tilhører den samme gruppe, i et array (via concat). Bemærk, at hvis du optimerer reduktion for kun at beholde de fem øverste array-elementer ved at tjekke dato, behøver du ikke færdiggørelsesfunktionen, og du vil bruge mindre hukommelse under kørsel af mapreduce (det vil også være hurtigere).
reduce = function (key, values) {
result={a:[]};
values.forEach( function(v) {
result.a = v.a.concat(result.a);
} );
return result;
}
Da jeg beholder alle værdier for hver tast, har jeg brug for en færdiggørelsesfunktion til kun at trække de seneste fem elementer ud pr. tast.
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);
}
Ved at bruge et skabelondokument, der ligner det, du har angivet, kører du dette ved at kalde kommandoen 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,
}
Hvert resultat har _id som gruppenavn og værdier som matrix af de seneste fem dokumenter fra samlingen for det gruppenavn.