Bạn chưa thể thực hiện việc này bằng cách sử dụng khung tổng hợp - bạn có thể nhận được giá trị $ max hoặc giá trị ngày cao nhất cho mỗi nhóm nhưng khung tổng hợp chưa có cách tích lũy N đầu cộng với không có cách nào để đẩy toàn bộ tài liệu vào tập kết quả (chỉ các trường riêng lẻ).
Vì vậy, bạn phải quay trở lại MapReduce. Đây là một cái gì đó sẽ hoạt động, nhưng tôi chắc chắn rằng có nhiều biến thể (tất cả đều yêu cầu bằng cách nào đó sắp xếp một mảng đối tượng dựa trên một thuộc tính cụ thể, tôi đã mượn giải pháp của mình từ một trong câu trả lời cho câu hỏi này .
Hàm ánh xạ - xuất ra tên nhóm dưới dạng khóa và toàn bộ phần còn lại của tài liệu dưới dạng giá trị - nhưng nó xuất ra dưới dạng tài liệu chứa một mảng vì chúng tôi sẽ cố gắng tích lũy một mảng kết quả cho mỗi nhóm:
map = function () {
emit(this.name, {a:[this]});
}
Hàm giảm sẽ tích lũy tất cả các tài liệu thuộc cùng một nhóm vào một mảng (thông qua concat). Lưu ý rằng nếu bạn tối ưu hóa giảm để chỉ giữ lại năm phần tử mảng trên cùng bằng cách kiểm tra ngày thì bạn sẽ không cần hàm hoàn thiện và bạn sẽ sử dụng ít bộ nhớ hơn trong khi chạy mapreduce (nó cũng sẽ nhanh hơn).
reduce = function (key, values) {
result={a:[]};
values.forEach( function(v) {
result.a = v.a.concat(result.a);
} );
return result;
}
Vì tôi đang giữ tất cả các giá trị cho mỗi khóa, tôi cần một hàm hoàn thiện để chỉ lấy ra năm phần tử mới nhất cho mỗi khóa.
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);
}
Sử dụng tài liệu mẫu tương tự như tài liệu bạn đã cung cấp, bạn chạy tài liệu này bằng cách gọi lệnh 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,
}
Mỗi kết quả có _id là tên nhóm và các giá trị dưới dạng mảng của năm tài liệu gần đây nhất từ bộ sưu tập cho tên nhóm đó.