Nie możesz jeszcze tego zrobić za pomocą struktury agregacji — możesz uzyskać wartość $max lub najwyższą datę dla każdej grupy, ale struktura agregacji nie ma jeszcze sposobu na zgromadzenie pierwszych N plus nie ma możliwości wypchnięcia całego dokumentu do zestawu wyników (tylko poszczególne pola).
Musisz więc wrócić do MapReduce. Oto coś, co zadziała, ale jestem pewien, że istnieje wiele wariantów (wszystkie wymagają jakoś posortowania tablicy obiektów na podstawie określonego atrybutu, pożyczyłem moje rozwiązanie od jednego z odpowiedzi na to pytanie .
Funkcja mapowania — wyświetla nazwę grupy jako klucz, a całą resztę dokumentu jako wartość — ale wyświetla ją jako dokument zawierający tablicę, ponieważ spróbujemy zgromadzić tablicę wyników na grupę:
map = function () {
emit(this.name, {a:[this]});
}
Funkcja zmniejszania zgromadzi wszystkie dokumenty należące do tej samej grupy w jedną tablicę (poprzez concat). Zwróć uwagę, że jeśli zoptymalizujesz zmniejszenie, aby zachować tylko pięć pierwszych elementów tablicy poprzez sprawdzenie daty, nie będziesz potrzebować funkcji finalize i zużyjesz mniej pamięci podczas uruchamiania mapreduce (będzie to również szybsze).
reduce = function (key, values) {
result={a:[]};
values.forEach( function(v) {
result.a = v.a.concat(result.a);
} );
return result;
}
Ponieważ zachowuję wszystkie wartości dla każdego klucza, potrzebuję funkcji finalize, która wyciągnie tylko pięć ostatnich elementów na klucz.
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);
}
Używając szablonu dokumentu podobnego do tego, który podałeś, uruchamiasz go, wywołując polecenie 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,
}
Każdy wynik ma _id jako nazwę grupy i wartości jako tablicę ostatnich pięciu dokumentów z kolekcji dla tej nazwy grupy.