Anda belum dapat melakukan ini menggunakan kerangka kerja agregasi - Anda bisa mendapatkan $max atau nilai tanggal teratas untuk setiap grup tetapi kerangka kerja agregasi belum memiliki cara untuk mengakumulasi N teratas ditambah tidak ada cara untuk mendorong seluruh dokumen ke dalam kumpulan hasil (hanya bidang individual).
Jadi, Anda harus kembali ke MapReduce. Berikut adalah sesuatu yang akan berfungsi, tetapi saya yakin ada banyak varian (semuanya memerlukan penyortiran array objek berdasarkan atribut tertentu, saya meminjam solusi saya dari salah satu jawaban dalam pertanyaan ini .
Fungsi peta - menampilkan nama grup sebagai kunci dan seluruh dokumen lainnya sebagai nilai - tetapi menampilkannya sebagai dokumen yang berisi larik karena kami akan mencoba mengumpulkan larik hasil per grup:
map = function () {
emit(this.name, {a:[this]});
}
Fungsi pengurangan akan mengakumulasikan semua dokumen milik grup yang sama ke dalam satu larik (melalui concat). Perhatikan bahwa jika Anda mengoptimalkan pengurangan untuk menyimpan hanya lima elemen larik teratas dengan memeriksa tanggal, maka Anda tidak memerlukan fungsi finalisasi, dan Anda akan menggunakan lebih sedikit memori selama menjalankan mapreduce (ini juga akan lebih cepat).
reduce = function (key, values) {
result={a:[]};
values.forEach( function(v) {
result.a = v.a.concat(result.a);
} );
return result;
}
Karena saya menyimpan semua nilai untuk setiap kunci, saya memerlukan fungsi finalize untuk mengeluarkan hanya lima elemen terbaru per kunci.
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);
}
Menggunakan dokumen template yang mirip dengan yang Anda berikan, Anda menjalankan ini dengan memanggil perintah 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,
}
Setiap hasil memiliki _id sebagai nama grup dan nilai sebagai larik dari lima dokumen terbaru dari koleksi untuk nama grup tersebut.