Pokud jde jen o to, dostat věci do 10 sekundových intervalů, můžete si trochu spočítat a projít to souhrnem:
db.collection.aggregate([
{ "$group": {
"_id": {
"year": { "$year": "$created_at" },
"month":{ "$month": "$created_at" },
"day": { "$dayOfMonth": "$created_at" },
"hour": { "$hour": "$created_at" },
"minute": { "$minute": "$created_at" },
"second": { "$subtract": [
{ "$second": "$created_at" },
{ "$mod": [
{ "$second": "$created_at" },
10
]}
]}
},
"count": { "$sum" : 1 }
}}
])
Takže to rozdělí věci na intervaly 10 sekund za minutu, kde k nim dochází s trochou matematického modu 10.
Myslím, že je to rozumné a byl by to nejrychlejší běžec, protože používá agregát. Pokud opravdu potřebujete, aby vaše sekvence, jak je ukázána, běžela 10 sekund od původně shodného času, můžete proces provést pomocí mapReduce:
Nejprve mapovač:
var mapper = function () {
if ( this.created_at.getTime() > ( last_date + 10000 ) ) {
if ( last_date == 0 ) {
last_date = this.created_at.getTime();
} else {
last_date += 10000;
}
}
emit(
{
start: new Date( last_date ),
end: new Date( last_date + 10000 )
},
this.created_at
);
}
Takže to bude vydávat data v intervalu 10 sekund, počínaje prvním datem a pak se interval prodlužuje pokaždé, když je něco nalezeno mimo rozsah
Nyní potřebujete redukci:
var reducer = function (key, values) {
return values.length;
};
Velmi jednoduché. Stačí vrátit délku předávaného pole.
Protože mapReduce funguje tak, jak funguje, nic, co nemělo více než jednu hodnotu, není předáno do reduktoru, takže to vyčistěte pomocí finalize:
var finalize = function (key, value) {
if ( typeof(value) == "object" ) {
value = 1;
}
return value;
};
Pak to stačí spustit, abyste získali výsledky. Všimněte si sekce "rozsah", která předává globální proměnnou, která má být použita v mapovači:
db.collection.mapReduce(
mapper,
reducer,
{
"out": { "inline": 1 },
"scope": { "last_date": 0 },
"finalize": finalize
}
)
Každý přístup pravděpodobně poskytne mírně odlišné výsledky, ale o to jde. Záleží na tom, který z nich skutečně chcete použít.
Vzhledem k vašemu komentáři byste mohli buď "zkontrolovat" výstup z kteréhokoli prohlášení a "doplnit mezery" programově. Obecně dávám přednost této možnosti, ale není to můj program a nevím, jak velkou sérii se snažíte z tohoto dotazu získat.
Na straně serveru můžete opravit "mapovač" a provést něco takového:
var mapper = function () {
if ( this.created_at.getTime() > ( last_date + 10000 ) ) {
if ( last_date == 0 ) {
last_date = this.created_at.getTime();
} else {
// Patching for empty blocks
var times = Math.floor(
( this.created_at.getTime() - last_date ) / 10000
);
if ( times > 1 ) {
for ( var i=1; i < times; i++ ) {
last_date += 10000;
emit(
{
start: new Date( last_date ),
end: new Date( last_date + 10000 )
},
0
);
}
}
// End patch
last_date += 10000;
}
}
emit(
{
start: new Date( last_date ),
end: new Date( last_date + 10000 )
},
this.created_at
);
}