Затем вместо применения операторов агрегации даты вместо этого применяйте «Date Math» для округления объект даты. Это часто может быть желательным, поскольку все драйверы представляют дату BSON в форме, которая обычно используется для манипуляций Date для всех языков, где это возможно:
db.datetest.aggregate([
{ "$group": {
"_id": {
"$add": [
{ "$subtract": [
{ "$subtract": [ "$date", new Date(0) ] },
{ "$mod": [
{ "$subtract": [ "$date", new Date(0) ] },
1000 * 60 * 60 * 24
]}
]},
new Date(0)
]
},
"click": { "$sum": 1 }
}}
])
Или, если это подразумевается в вопросе о том, что требуемый интервал группировки - это «ведра» в 15 дней, затем просто примените это к числовому значению в $mod
:
db.datetest.aggregate([
{ "$group": {
"_id": {
"$add": [
{ "$subtract": [
{ "$subtract": [ "$date", new Date(0) ] },
{ "$mod": [
{ "$subtract": [ "$date", new Date(0) ] },
1000 * 60 * 60 * 24 * 15
]}
]},
new Date(0)
]
},
"click": { "$sum": 1 }
}}
])
Применяемая основная математика заключается в том, что когда вы $subtract
два объекта Date
, возвращаемый результат будет миллисекундами разного числа. Таким образом, эпоха представлена Date(0)
как базой для преобразования в любом конструкторе языка.
С числовым значением применяется «modulo» ( $mod
) округлить дату (вычесть остаток от деления) до требуемого интервала. Быть либо:
1000 миллисекунд x 60 секунд * 60 минут * 24 часа = 1 день
blockquote>Или
1000 миллисекунды x 60 секунд * 60 минут * 24 часа * 15 дней = 15 дней
blockquote>Таким образом, он является гибким для любого интервала, который вам нужен.
Точно так же,
$add
между «числовым» значением и объектомDate
будет возвращать объектDate
, эквивалентный значению millseconds для обоих объектов в сочетании (epoch равно 0, поэтому 0 плюс разница - это преобразованная дата).Легко отображается и воспроизводится в следующем листинге:
var now = new Date(); var bulk = db.datetest.initializeOrderedBulkOp(); for ( var x = 0; x < 60; x++ ) { bulk.insert({ "date": new Date( now.valueOf() + ( 1000 * 60 * 60 * 24 * x ))}); } bulk.execute();
И запуск второго примера с 15-дневными интервалами:
{ "_id" : ISODate("2016-04-14T00:00:00Z"), "click" : 12 } { "_id" : ISODate("2016-03-30T00:00:00Z"), "click" : 15 } { "_id" : ISODate("2016-03-15T00:00:00Z"), "click" : 15 } { "_id" : ISODate("2016-02-29T00:00:00Z"), "click" : 15 } { "_id" : ISODate("2016-02-14T00:00:00Z"), "click" : 3 }
Или аналогичное распределение в зависимости от текущей даты, когда выполняется листинг, и, конечно, 15-дневные интервалы будут согласованы с даты эпохи.
Использование метода «Math» немного легче настроить, особенно если вы хотите настроить периоды времени для diff в то время как вы можете аналогичным образом скорректировать цифру, добавив / вычитая числовое отличие от UTC.