Если вы хотите, чтобы Дата oject возвращалась напрямую
Затем вместо применения Операторов агрегации даты вместо применения "Математика даты", чтобы округлить объект даты. Это часто может быть желательно, так как все драйверы представляют дату BSON в форме, которая обычно используется для манипуляции датой для всех языков, где это возможно:
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 день
или
1000 миллисекунд x 60 секунд * 60 минут * 24 часа * 15 дней = 15 дней
Так что он гибок к любому интервалу, который вам необходим.
По тому же показателю сверху операция $add
между «числовым» значением и объектом Date
вернет объект Date
, эквивалентный значению в миллисекундах обоих объектов вместе (эпоха 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-дневные интервалы будут согласованы с даты эпохи.
Использование метода "Математика" немного проще в настройке, особенно если вы хотите настроить периоды времени для разных часовых поясов в агрегированном выводе, где вы можете аналогичным образом выполнить числовую регулировку, добавляя / вычитая числовую разницу из UTC.