MongoDB 时间序列聚合

Posted

技术标签:

【中文标题】MongoDB 时间序列聚合【英文标题】:MongoDB Time Series Aggregation 【发布时间】:2015-10-11 03:18:34 【问题描述】:

我正在以可配置的时间间隔读取传感器数据,但对于本示例,假设每 30 秒一次。我希望能够按小时、天、周、月和年的间隔对数据进行分组。我还希望能够在相同的时间间隔内聚合一组传感器的平均值。

示例用例:

1.获取传感器 ID 的最近 4 个月总计:x

2.获取具有 group_id 的传感器最近 4 个月的平均总数:y

用例 2 阐明

以下都具有相同的group_id

sensor_id | month 1 | month 2 | month 3 | month 4
     1    |   10    |   15    |   5     |    10
     2    |   20    |   30    |   30    |    5
     3    |   5     |   20    |   40    |    20

输出

month1 : 11.67, month2: 21.67, month3: 25, month4: 11.67

我见过很多在 MongoDB 中存储时间序列数据的方法。我正在考虑为每个间隔收集一个集合,包括原始时间值以及让每个文档在某个时间段后过期。

MonthPoint 示例文档


    "_id": 
        "$oid": "55270059a791051d4a4e0e41"
    ,
    "sensor_id": "1",
    "group_id" : "4",
    "timestamp": 
        "$date": "2015-04-01T00:00:00.000Z"
    ,
    "sum": 40
    "count": 200

对于进入的每个点,我都必须对每个集合执行写入操作,但读取数据会很快。

用例 1,将是一个非常简单的查询:

MonthPoints.find(
    sensor_id : x,
    timestamp : 
        $gte: startDate,
        $lt: currentDate
    
);

但是我将如何聚合用例 2?是否有可能在一个聚合中实现这一目标?我看到了如何使用 4 个单独的聚合来实现,通过 group_id 获取每个月的平均值。

【问题讨论】:

是的,最新的编辑包含一个示例文档。 【参考方案1】:

我有以下收藏:

> db.mpoints.find()
 "_id" : ObjectId("55ae6d35931d911f97d09977"), "g" : 55, "s" : 1, "v" : 10, "d" : ISODate("2015-03-31T00:00:00Z") 
 "_id" : ObjectId("55ae6d3d931d911f97d09978"), "g" : 55, "s" : 2, "v" : 20, "d" : ISODate("2015-03-31T00:00:00Z") 
 "_id" : ObjectId("55ae6d42931d911f97d09979"), "g" : 55, "s" : 3, "v" : 5, "d" : ISODate("2015-03-31T00:00:00Z") 
 "_id" : ObjectId("55ae6d49931d911f97d0997a"), "g" : 11, "s" : 3, "v" : 5, "d" : ISODate("2015-03-31T00:00:00Z") 
 "_id" : ObjectId("55ae6d54931d911f97d0997b"), "g" : 55, "s" : 3, "v" : 20, "d" : ISODate("2015-04-30T00:00:00Z") 
 "_id" : ObjectId("55ae6d8a931d911f97d0997c"), "g" : 55, "s" : 2, "v" : 20, "d" : ISODate("2015-04-30T00:00:00Z") 
 "_id" : ObjectId("55ae6dc2fc560cbbe2b22400"), "g" : 55, "s" : 1, "v" : 50, "d" : ISODate("2015-04-30T00:00:00Z") 

字段的映射为:

d - 是日期 - 我把它作为本月的最后一个日期。您也可以将其作为本月的第一个日期。没关系。 g - 你的群号 s - 你的传感器 ID v - 你的价值

聚合调用是

db.mpoints.aggregate([

    $match: 
        "g": 55,
        "d": 
            "$gte": ISODate("2015-03-31T00:00:00Z"),
            "$lte": ISODate("2015-04-30T00:00:00Z")
        
    
,

    $group: 
        "_id": "$d",
        total: 
            $sum: '$v'
        ,
        count: 
             $sum: 1
        
    

])

结果是

 "_id" : ISODate("2015-04-30T00:00:00Z"), "total" : 90, "count" : 3 
 "_id" : ISODate("2015-03-31T00:00:00Z"), "total" : 35, "count" : 3 

您将获得每个月的总数和该月的条目数。

【讨论】:

以上是关于MongoDB 时间序列聚合的主要内容,如果未能解决你的问题,请参考以下文章

使用聚合管道聚合 MongoDB 中的时间戳集合

如何在 MongoDB 中聚合时间序列数据

MongoDB慢聚合时间

MongoDB 时间序列聚合

带有大量文档的 MongoDb 聚合查找?

带有大量文档的 MongoDb 聚合查找?