Din fejl er, hvordan du beregner _id for $group operator, specifikt dens second del:
second: { $subtract: [
{ $second: "$time" },
{ $mod: [
{ $second: "$time" },
timeBlock / 1000
]}
]}
Så i stedet for at opdele alle dine data i 10 timeBlock millisekunder lange bidder fra new Date(end - 10 * timeBlock) , opdeler du det i 11 bidder, startende fra den nærmeste divisor af timeBlock .
For at rette det skal du først beregne delta = end - $time og brug det så i stedet for den originale $time for at bygge dit _id .
Her er et eksempel på, hvad jeg mener:
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) {
// ...
})
Jeg anbefaler dig også at bruge råtidsværdier (i millisekunder), fordi det er meget nemmere, og fordi det forhindrer dig i at lave en fejl. Du kan caste time ind i timeParts efter $group ved hjælp af $project operatør.