MongoDB 5.0 發佈的新功能,僅在 5.0 之後的版本提供。
時間序列集合(Time series collection) 是一個新型態的集合,有別於 capped collection
與 一般 Collection
,它有諸多限制:
drop collection
capped
或 一般
collection,反之亦然unique
(_id為例外), partial
metaField
, timeField
(後面說明)兩欄位僅有在建立 Collection 才可以決定,之後無法修改。看了這麼多限制後,還是不知道什麼是時間序列集合。基本上該功能就可以想像成依照時間來進行統計分析的集合,像是股票資料或天氣資料這種,依照時間進行,然後去統計分析股票價位高低或者溫度的高低。
timeField
時間欄位,指定要做為統計的時間欄位,必須是要時間的資料型別
metaField
分群的欄位,統計資料會自動以該欄位進行分群。
因為只能指定一個欄位,所以可以進行變通,例如原本是 { "name": "Bruce"}
改為 { "name": "Bruce", "lastName": "Lee" }
granularity
統計時間粒度,可以是 seconds
, minutes
或 hours
有著前面的知識後我們來準備一個範例,建立語法以及預設資料如下
db.createCollection("order.ts", {
timeseries: {
timeField: "orderDate",
metaField: "customerName",
granularity: "hours"
},
expireAfterSeconds: 3600*31*6
});
資料範本
{
"customerId": 10001,
"customerName": { "name":"Bruce", "lastName": "Lee" },
"orderPrize": 1280,
"orderStatus": 1,
"orderDate": ISODate("2021-09-01T11:00:00.000Z"),
"deliverDate": ISODate("2021-09-05T15:00:00.000Z")
},
{
"customerId": 10001,
"customerName": { "name":"Bruce", "lastName": "Lee" },
"orderPrize": 1880,
"orderStatus": 3,
"orderDate": ISODate("2021-09-01T12:00:00.000Z"),
"deliverDate": ISODate("2021-09-06T16:00:00.000Z")
},
{
"customerId": 10001,
"customerName": { "name":"Bruce", "lastName": "Lee" },
"orderPrize": 540,
"orderStatus": 2,
"orderDate": ISODate("2021-09-02T03:00:00.000Z"),
"deliverDate": ISODate("2021-09-07T17:00:00.000Z")
},
{
"customerId": 10002,
"customerName": { "name":"Old", "lastName": "Chou" },
"orderPrize": 2300,
"orderStatus": 1,
"orderDate": ISODate("2021-09-01T10:00:00.000Z"),
"deliverDate": ISODate("2021-09-07T14:00:00.000Z")
},
{
"customerId": 10003,
"customerName": "Kate",
"orderPrize": 2890,
"orderStatus": 3,
"orderDate": ISODate("2021-09-01T12:00:00.000Z"),
"deliverDate": ISODate("2021-09-07T14:00:00.000Z")
}
timeseries> show collections
order.ts [time-series]
system.buckets.order.ts
system.views
建立完後我們看到除了原本的 order.ts
collection 有被標註為 [time-series]
,還多了兩個:
system.views
{
"_id" : "timeseries.order.ts",
"viewOn" : "system.buckets.order.ts",
"pipeline" : [
{
"$_internalUnpackBucket" : {
"timeField" : "orderDate",
"metaField" : "customerName",
"bucketMaxSpanSeconds" : 2592000,
"exclude" : []
}
}
]
}
裡面存放了 bukets 的 view,與建立的資訊
system.buckets.order.ts
這裡總共有四筆資料,分別是按照 metaField
作為 group
統計而來的,礙於篇幅,我舉其中一個例子並分段來看
Part 1
{
"_id" : ObjectId("612ec2808b826f0fc8ce4afa"),
"control" : {
"version" : 1,
"min" : {
"_id" : ObjectId("614eee10ebdbba2a6c81adbd"),
"customerId" : 10001.0,
"orderPrize" : 540.0,
"orderStatus" : 1.0,
"orderDate" : ISODate("2021-09-01T00:00:00.000Z"),
"deliverDate" : ISODate("2021-09-05T15:00:00.000Z")
},
"max" : {
"_id" : ObjectId("614eee10ebdbba2a6c81adbf"),
"customerId" : 10001.0,
"orderPrize" : 1880.0,
"orderStatus" : 3.0,
"orderDate" : ISODate("2021-09-02T03:00:00.000Z"),
"deliverDate" : ISODate("2021-09-07T17:00:00.000Z")
}
},
這邊直接幫你算出 metaField { "name":"Bruce", "lastName": "Lee" }
分類裡的每個項目的最小值與最大值,要是能設定多算一些統計值也是不錯吧。
有個小疑問是最小值的 orderDate 值是 ISODate("2021-09-01T00:00:00.000Z")
但原始數據明明是 ISODate("2021-09-01T10:00:00.000Z")
,可能會是個 bug?
Part 2
"meta" : {
"lastName" : "Lee",
"name" : "Bruce"
},
就是剛開始建立 Collection 時指定用來分群的 metaField
Part3
"data" : {
"orderDate" : {
"0" : ISODate("2021-09-01T11:00:00.000Z"),
"1" : ISODate("2021-09-01T12:00:00.000Z"),
"2" : ISODate("2021-09-02T03:00:00.000Z")
},
"customerId" : {
"0" : 10001.0,
"1" : 10001.0,
"2" : 10001.0
},
"deliverDate" : {
"0" : ISODate("2021-09-05T15:00:00.000Z"),
"1" : ISODate("2021-09-06T16:00:00.000Z"),
"2" : ISODate("2021-09-07T17:00:00.000Z")
},
"orderPrize" : {
"0" : 1280.0,
"1" : 1880.0,
"2" : 540.0
},
"_id" : {
"0" : ObjectId("614eee10ebdbba2a6c81adbd"),
"1" : ObjectId("614eee10ebdbba2a6c81adbe"),
"2" : ObjectId("614eee10ebdbba2a6c81adbf")
},
"orderStatus" : {
"0" : 1.0,
"1" : 3.0,
"2" : 2.0
}
}
從這邊可以看到 data
這個項目裡面存放的就是各個欄位的原始數據,如果要做聚合、統計都能夠從這邊直接取用,順序也是按照寫入的順序。
看到這邊我就不再繼續延伸使用 aggregation
示範內容了,基本上 time series collection
就是幫你把資料按照另一個格式進行儲存,讓你可以更快的在感興趣的欄位進行統計。
另外因為是 demo 概念,沒有建立 index,請務必在使用時加上相對應得索引,使你的查詢更加有效率。
例如幫你自動分桶的集合 system.buckets.order.ts
能這樣做,或者是原本的 order.ts
集合。
本系列文章會同步發表於我個人的部落格 Pie Note