Có một số cách để tiếp cận điều này tùy thuộc vào định dạng đầu ra nào phù hợp nhất với nhu cầu của bạn. Lưu ý chính là với "khung tổng hợp" bản thân nó, bạn thực sự không thể trả về một thứ gì đó "được đúc" dưới dạng ngày tháng, nhưng bạn có thể nhận các giá trị dễ dàng được cấu trúc lại thành một Date
đối tượng khi xử lý kết quả trong API của bạn.
Cách tiếp cận đầu tiên là sử dụng "Toán tử Tổng hợp Ngày" có sẵn cho khuôn khổ tổng hợp:
db.collection.aggregate([
{ "$match": {
"time": { "$gte": startDate, "$lt": endDate }
}},
{ "$group": {
"_id": {
"year": { "$year": "$time" },
"dayOfYear": { "$dayOfYear": "$time" },
"hour": { "$hour": "$time" },
"minute": {
"$subtract": [
{ "$minute": "$time" },
{ "$mod": [ { "$minute": "$time" }, 10 ] }
]
}
},
"count": { "$sum": 1 }
}}
])
Nó trả về một khóa tổng hợp cho _id
chứa tất cả các giá trị bạn muốn cho một "ngày". Ngoài ra, nếu luôn luôn chỉ trong vòng "giờ" thì chỉ cần sử dụng phần "phút" và tính ra ngày thực tế dựa trên startDate
lựa chọn phạm vi của bạn.
Hoặc bạn có thể chỉ sử dụng "Toán ngày tháng" đơn giản để lấy mili giây kể từ "kỷ nguyên" có thể được cung cấp lại trực tiếp cho một trình tạo ngày tháng.
db.collection.aggregate([
{ "$match": {
"time": { "$gte": startDate, "$lt": endDate }
}},
{ "$group": {
"_id": {
"$subtract": [
{ "$subtract": [ "$time", new Date(0) ] },
{ "$mod": [
{ "$subtract": [ "$time", new Date(0) ] },
1000 * 60 * 10
]}
]
},
"count": { "$sum": 1 }
}}
])
Trong mọi trường hợp, những gì bạn không muốn làm là sử dụng $project
trước khi thực sự áp dụng $group
. Là một "giai đoạn đường ống", $project
phải "xoay vòng" mặc dù tất cả các tài liệu đã được chọn và "chuyển đổi" nội dung.
Điều này cần thời gian và thêm vào tổng số thực thi của truy vấn. Bạn chỉ cần đăng ký vào $group
trực tiếp như đã được hiển thị.
Hoặc nếu bạn thực sự "thuần túy" về Date
đối tượng được trả lại mà không cần xử lý bài đăng, thì bạn luôn có thể sử dụng "mapReduce" , vì các hàm JavaScript thực sự cho phép ghi lại dưới dạng ngày tháng, nhưng chậm hơn khung tổng hợp và tất nhiên là không có phản hồi con trỏ:
db.collection.mapReduce(
function() {
var date = new Date(
this.time.valueOf()
- ( this.time.valueOf() % ( 1000 * 60 * 10 ) )
);
emit(date,1);
},
function(key,values) {
return Array.sum(values);
},
{ "out": { "inline": 1 } }
)
Đặt cược tốt nhất của bạn là sử dụng tính năng tổng hợp, vì việc chuyển đổi phản hồi khá dễ dàng:
db.collection.aggregate([
{ "$match": {
"time": { "$gte": startDate, "$lt": endDate }
}},
{ "$group": {
"_id": {
"year": { "$year": "$time" },
"dayOfYear": { "$dayOfYear": "$time" },
"hour": { "$hour": "$time" },
"minute": {
"$subtract": [
{ "$minute": "$time" },
{ "$mod": [ { "$minute": "$time" }, 10 ] }
]
}
},
"count": { "$sum": 1 }
}}
]).forEach(function(doc) {
doc._id = new Date(doc._id);
printjson(doc);
})
Và sau đó bạn có đầu ra phân nhóm khoảng thời gian với Date
thực đối tượng.