Ако става въпрос само за получаване на нещата в рамките на интервали от 10 секунди, можете да направите малко математика и да пуснете това чрез агрегат:
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 }
}}
])
Така че нещата се разделят на интервали от 10 секунди в минута, където се случват с малко модифициране 10 математика.
Мисля, че това е разумно и би било най-бързият бегач, тъй като използва агрегат. Ако наистина се нуждаете вашата последователност, както е показано, да бъде работеща 10 секунди от първоначално съвпадащо време, тогава можете да извършите процеса с mapReduce:
Първо картограф:
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
);
}
Така че това ще излъчи дати в рамките на интервал от 10 секунди, започвайки с първата дата и след това увеличавайки интервала всеки път, когато се намери нещо извън диапазона
Сега имате нужда от редуктор:
var reducer = function (key, values) {
return values.length;
};
Много просто. Просто върнете дължината на предадения масив.
Тъй като mapReduce работи по начина, по който работи, всичко, което няма повече от една стойност, не се предава на редуктора, така че почистете това с finalize:
var finalize = function (key, value) {
if ( typeof(value) == "object" ) {
value = 1;
}
return value;
};
След това просто го стартирайте, за да получите резултатите. Обърнете внимание на секцията „обхват“, която предава глобална променлива, която да се използва в картографа:
db.collection.mapReduce(
mapper,
reducer,
{
"out": { "inline": 1 },
"scope": { "last_date": 0 },
"finalize": finalize
}
)
Всеки подход вероятно ще даде малко по-различни резултати, но това е смисълът. Зависи кой всъщност искате да използвате.
Като се има предвид вашият коментар, можете или да „инспектирате“ изхода от който и да е израз и да „попълните празнините“ програмно, така да се каже. По принцип предпочитам тази опция, но това не е моята програма и не знам колко голяма поредица се опитвате да извлечете от тази заявка.
От страна на сървъра можете да закърпите „картографа“, за да направите нещо като това:
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
);
}