DAY27 MongoDB Time Series Collection

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


<<:  Powershell 入门添加参数帮助信息

>>:  Day 25: ELK持续监控与Dockerize

[Android Studio] 每日小技巧 - 在 Android Studio 中快速向 Google 作关键字搜索

身为开发时程紧凑的工程师 遇到问题或是疑惑时必须要能快速的排除 通常在专案中遇到不熟悉的物件,想到 ...

关於 Mac「启动磁碟已满」问题的解决方案以及如何最佳化磁碟空间

Mac 启动磁碟满了怎麽办?当你耗尽了磁碟的储存空间後,你将无法存取资料档案。不少 Mac 用户都曾...

DAY30 结语

哇~~~终於完成三十天的文章了,这里面记录了满满我对於这个专案学习的过程,以及在最後展现出成果实在是...

想抢先经营网路行销,必需先了解5件事

在辅导企业高层主管上课时候,我常跟他们说如果不了解你的产品市场那麽就无法开始执行方案,因此在这个後疫...

android studio 30天学习笔记-day 10-rxjava2+retrofit

前言 retrofit负责请求网路资料请求,rxjava负责异步执行、thread之间的切换,今天实...