一 . 背景需求
在日常的業務需求中,我們往往會根據時間段來統計數據。例如,統計每小時的下單量;每天的庫存變化,這類信息數據對運營管理很重要。
這類數據統計依賴於各個時間維度,年月日、時分秒都有可能。因為需求變化多樣,並且表的設計有嚴格的規范,我們不可能將訂單的下單時間分別拆分存儲到 年、月、日、時、分、秒、毫秒列(字段)中。在實際應用中,我們一般都是通過轉換函數進行時間轉換的。
大家可能對關系型數據庫(例如,SQL Server、MySQL)中的時間轉換函數和依據時間段進行聚合操作比較熟悉了,但是對MongoDB中的時間轉換和依據時間聚合比較陌生。所以,我們有必要花費一定時間進行梳理學習一下,拓展豐富自己的知識。
二 . SQL Server數據庫關於時間的轉換和聚合
為了清楚的了解這類需求,了解時間轉換和統計,我們先從大家熟悉的SQL Server 入手。例如,我們將時間數據存儲為datetime類型。
首先,回顧下SQL Server的時間轉換函數。
1.通過YEAR(),MONTH(),DAY() 獲取年月日數據。

2.通過DATEPART() 函數 返回日期/時間的單獨部分,比如年、月、日、小時、分鍾等等。

3.datename () 返回代表指定日期的指定日期部分的字符串。此函數與DATEPART() 類似。

此外,還可以通過convert() 等函數進行轉換,再次不再贅述。
通過這些函數,我們可以進行時間格式的轉換,在轉換函數的基礎上,可以進行時間段內數據量的統計。
例如:基於DATEPART() 函數, 統計2017-10-10到2017-11-10表中每天的數據量。

也可以基於convert() 函數進行統計
三 . MongoDB 數據庫關於時間的轉換和聚合
以上操作是在SQL Server上進行,如果在MongoDB中,應該借助什么的函數進行類似的轉換和統計呢?
如果查看顯示 各種格式的時間,可以通過 $dateToString 進行轉換。
例如通過轉換函數$dateToString,將集合temp_MongoDateTime中的字段Rec_CreateTime轉換為 年 字段、月 字段、日 字段、年-月-日、和 時:分:秒:毫秒 字段
代碼為:
db.temp_MongoDateTime.aggregate(
[
{
$project: {
"_id":0,
"Rec_CreateTime":1,
Year: { $dateToString: { format: "%Y", date: "$Rec_CreateTime" } },
Month: { $dateToString: { format: "%m", date: "$Rec_CreateTime" } },
Day: { $dateToString: { format: "%d", date: "$Rec_CreateTime" } },
yearMonthDay: { $dateToString: { format: "%Y-%m-%d", date: "$Rec_CreateTime" } },
Time: { $dateToString: { format: "%H:%M:%S:%L", date: "$Rec_CreateTime"} }
}
}
]
)
查詢效果如下:

除了$dateToString轉換函數外,MongoDBDB 還有獲取年月日、時分秒的函數,甚至還提供了處於一年中的多少天,一周的第幾天等。
主要函數為$year、$month、$dayOfMonth、 $hour、$minute、$second、$dayOfYear、$dayOfWeek 等。
我們直接看下面的例子好了。執行代碼:
db.temp_MongoDateTime.aggregate(
[
{
$project:
{
"_id":0,
"Rec_CreateTime":1,
year: { $year: "$Rec_CreateTime" },
month: { $month: "$Rec_CreateTime" },
day: { $dayOfMonth: "$Rec_CreateTime" },
hour: { $hour: "$Rec_CreateTime" },
minutes: { $minute: "$Rec_CreateTime" },
seconds: { $second: "$Rec_CreateTime" },
milliseconds: { $millisecond: "$Rec_CreateTime" },
dayOfYear: { $dayOfYear: "$Rec_CreateTime" },
dayOfWeek: { $dayOfWeek: "$Rec_CreateTime" },
week: { $week: "$Rec_CreateTime" }
}
}
]
)

上面的2個例子都是時間轉換,如果按照時間段集合統計數據呢?其實基於上面的時間轉換函數,借助MongoDB的聚合框架,同樣可以輕松實現。
例如統計1-12 月份,每個月份的數據量,即那個月是旺季。此時基於時間轉換函數 $month,執行代碼如下:
db.temp_MongoDateTime.aggregate(
[
{
$match:{}
},
{
$group:{_id:{$month:"$Rec_CreateTime"},
count:{$sum:1}}
}
]
)
查詢效果如下:

上面的數據顯示:集合中的記錄按月聚合,10月份有341筆;9月份有48筆。其中字段_id 代表了月份。
我們再舉一個例子,例如統計 集合temp_MongoDateTime 在 2016-10-05 05:51:50 到 2018-10-06 05:51:50 這段時間內,0-24 小時內,每小時的分布情況。即,每天那個時辰(小時)下單量比較多。
此時基於時間轉換函數 $hour ,代碼如下:
db.temp_MongoDateTime.aggregate(
[
{
$match:{
"Rec_CreateTime":{$gte:ISODate("2016-10-05 05:51:50"),$lte:ISODate("2018-10-06 05:51:50")}
}
},
{$group:{
_id:{ $hour: "$Rec_CreateTime" },
count:{$sum:1}
}
}
]
)
查詢結果顯示如下:

再舉一個關於時間聚合統計的例子,這個例子是基於時間轉換函數$dateToString的。
例如統計每天的數據量,即每天的數據分布情況。這個每天是按 年-月-日統計分布的。
代碼如下:
db.temp_MongoDateTime.aggregate(
[
{
$match:{
"Rec_CreateTime":{$gte:ISODate("2016-10-05 05:51:50"),$lte:ISODate("2018-10-06 05:51:50")}
}
},
{$group:{
_id:{ $dateToString: { format: "%Y-%m-%d", date: "$Rec_CreateTime" } },
count:{$sum:1}
}
}
]
)
查詢效果顯示如下:

四 . 總結
和關系型數據庫 SQL Server 一樣,MongoDB數據庫通過自身的時間轉換函數,例如, $dateToString、$year、$month、$dayOfMonth、 $hour、$minute、$second、$dayOfYear、$dayOfWeek等,也可以輕松實現時間轉換和基於時間段的聚合統計。
本文版權歸作者所有,未經作者同意不得轉載,謝謝配合!!!
