Вашата грешка е как изчислявате _id
за $group
оператор, по-специално неговият second
част:
second: { $subtract: [
{ $second: "$time" },
{ $mod: [
{ $second: "$time" },
timeBlock / 1000
]}
]}
Така че, вместо да разделяте всичките си данни на 10 timeBlock
милисекунди дълги части, започващи от new Date(end - 10 * timeBlock)
, вие го разделяте на 11 части, започвайки от най-близкия делител на timeBlock
.
За да го коригирате, първо трябва да изчислите delta = end - $time
и след това го използвайте вместо оригиналния $time
за изграждане на вашия _id
.
Ето пример за това, което имам предвид:
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) {
// ...
})
Също така ви препоръчвам да използвате необработени стойности за време (в милисекунди), защото е много по-лесно и защото ще ви предпази от грешка. Можете да зададете time
в timeParts
след $group
използвайки $project
оператор.