iT邦幫忙

2021 iThome 鐵人賽

DAY 27
0
Software Development

MongoDB披荊斬棘之路系列 第 27

DAY27 MongoDB Time Series Collection

  • 分享至 

  • xImage
  •  

DAY27 MongoDB Time Series Collection

什麼是 Time series collection

MongoDB 5.0 發佈的新功能,僅在 5.0 之後的版本提供。
時間序列集合(Time series collection) 是一個新型態的集合,有別於 capped collection一般 Collection,它有諸多限制:

  • 僅支援 Read / Insert
  • 無法 Delete / Update,只能夠 drop collection
  • document 最大 4MB
  • 無法轉為 capped一般 collection,反之亦然
  • 沒辦法設定 Index 的 unique(_id為例外), partial
  • metaField, timeField (後面說明)兩欄位僅有在建立 Collection 才可以決定,之後無法修改。
  • Collection 無法 sharding

看了這麼多限制後,還是不知道什麼是時間序列集合。基本上該功能就可以想像成依照時間來進行統計分析的集合,像是股票資料或天氣資料這種,依照時間進行,然後去統計分析股票價位高低或者溫度的高低。

Time series collection 三大設定

  • timeField
    時間欄位,指定要做為統計的時間欄位,必須是要時間的資料型別

  • metaField
    分群的欄位,統計資料會自動以該欄位進行分群。
    因為只能指定一個欄位,所以可以進行變通,例如原本是 { "name": "Bruce"} 改為 { "name": "Bruce", "lastName": "Lee" }

  • granularity
    統計時間粒度,可以是 seconds, minuteshours

建立 Time series collection

有著前面的知識後我們來準備一個範例,建立語法以及預設資料如下

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")
}

查看 time series collection

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


上一篇
DAY26 MongoDB 匯入與匯出資料
下一篇
DAY28 MongoDB Atlas 付費監控內容
系列文
MongoDB披荊斬棘之路30
.

尚未有邦友留言

立即登入留言