Jeśli chodzi tylko o uzyskanie wyników w odstępach 10-sekundowych, możesz trochę policzyć i przeprowadzić to przez agregację:
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 }
}}
])
To rozkłada rzeczy na interwały 10 sekund na minutę, w których występują przy odrobinie matematyki mod 10.
Myślę, że to rozsądne i byłbym najszybszym biegaczem, ponieważ używa kruszywa. Jeśli naprawdę potrzebujesz, aby sekwencja, jak pokazano, trwała 10 sekund od początkowo dopasowanego czasu, możesz wykonać ten proces za pomocą mapReduce:
Najpierw twórca map:
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
);
}
To spowoduje wyemitowanie dat w przedziale 10 sekund, zaczynając od pierwszej daty, a następnie zwiększając interwał za każdym razem, gdy coś znajdzie się poza zakresem
Teraz potrzebujesz reduktora:
var reducer = function (key, values) {
return values.length;
};
Bardzo prosta. Po prostu zwróć długość przekazanej tablicy.
Ponieważ mapReduce działa tak, jak działa, wszystko, co nie ma więcej niż jednej wartości, nie jest przekazywane do reduktora, więc posprzątaj to za pomocą finalize:
var finalize = function (key, value) {
if ( typeof(value) == "object" ) {
value = 1;
}
return value;
};
Następnie po prostu uruchom go, aby uzyskać wyniki. Zwróć uwagę na sekcję „scope”, która przekazuje zmienną globalną, która ma być używana w programie mapującym:
db.collection.mapReduce(
mapper,
reducer,
{
"out": { "inline": 1 },
"scope": { "last_date": 0 },
"finalize": finalize
}
)
Każde podejście prawdopodobnie da nieco inne wyniki, ale o to właśnie chodzi. To zależy od tego, którego faktycznie chcesz użyć.
Biorąc pod uwagę Twój komentarz, możesz albo „sprawdzić” wyniki z obu stwierdzeń i „uzupełnić luki” niejako programowo. Generalnie wolę tę opcję, ale to nie jest mój program i nie wiem, jak dużą serię próbujesz pobrać z tego zapytania.
Po stronie serwera możesz załatać „mappera”, aby zrobić coś takiego:
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
);
}