Lỗi của bạn là cách bạn tính toán _id cho $group toán tử, cụ thể là second của nó phần:
second: { $subtract: [
{ $second: "$time" },
{ $mod: [
{ $second: "$time" },
timeBlock / 1000
]}
]}
Vì vậy, thay vì chia nhỏ tất cả dữ liệu của bạn thành 10 timeBlock đoạn dài mili giây bắt đầu từ new Date(end - 10 * timeBlock) , bạn đang chia nó thành 11 phần bắt đầu từ ước số gần nhất của timeBlock .
Để khắc phục, trước tiên bạn nên tính toán delta = end - $time và sau đó sử dụng nó thay vì $time ban đầu để xây dựng _id của bạn .
Đây là một ví dụ về ý tôi muốn nói:
Document.aggregate({
$match: {
time: {
$gte: new Date(end - 10 * timeBlock),
$lt: new Date(end)
}
}
}, {
$project: {
time: 1,
delta: { $subtract: [
new Date(end),
"$time"
]}
}
}, {
$project: {
time: 1,
delta: { $subtract: [
"$delta",
{ $mod: [
"$delta",
timeBlock
]}
]}
}
}, {
$group: {
_id: { $subtract: [
new Date(end),
"$delta"
]},
count: { $sum: 1 }
}
}, {
$project: {
time: "$_id",
count: 1,
_id: 0
}
}, {
$sort: {
time: 1
}
}, function(err, result) {
// ...
})
Tôi cũng khuyên bạn nên sử dụng các giá trị thời gian thô (tính bằng mili giây), vì nó dễ dàng hơn nhiều và vì nó sẽ giúp bạn không mắc lỗi. Bạn có thể truyền time vào timeParts sau $group sử dụng $project nhà điều hành.