Mogodb将值分成5分钟的间隔,并在间隔组内返回最近的值

时间:2015-09-29 12:42:15

标签: mongodb mongodb-query aggregation-framework

我的Mongo数据库包含以下文档:

{
   "timestamp": ISODate("2015-09-27T15:28:06.0Z"),
    "value": '123'
},
{
   "timestamp": ISODate("2015-09-27T15:31:06.0Z"),
    "value": '737'
},
{
   "timestamp": ISODate("2015-09-27T15:35:00.0Z"),
    "value": '456'
},
{
   "timestamp": ISODate("2015-09-27T15:40:20.0Z"),
    "value": '789'
}

...等...

我想要做的是以5分钟的间隔聚合这些,而不是获得最新的(最新的时间戳)值每组5分钟

所以基本上步骤是:

1)分成5分钟的小组

2)返回5分钟时间戳以及在此5分钟组内具有最新时间戳的文档的值

基于此以及我上面的文件,返回的文件应该是:

{
    "timestamp": ISODate("2015-09-27T15:25:00.0Z"),
    "value": '123'
},
{
    "timestamp": ISODate("2015-09-27T15:35:00.0Z"),
    "value": '456' // 456 has a newer timestamp than 737, which are in the same 5 minute range
},
{
    "timestamp": ISODate("2015-09-27T15:40:00.0Z"),
    "value": '789'
}

我尝试按照此处所述的5分钟间隔进行分组:https://stackoverflow.com/a/26814496/1007236

从那里开始,我无法找到如何在每个5分钟组内返回最新值。

我该怎么做?

1 个答案:

答案 0 :(得分:1)

你可以通过一个非常简单的日期数学应用来解决这个问题:

db.collection.aggregate([
    { "$sort": { "timestamp": 1 } },
    { "$group": {
        "_id": {
            "$add": [
                { "$subtract": [
                    { "$subtract": [ "$timestamp", new Date(0) ] },
                    { "$mod": [
                        { "$subtract": [ "$timestamp", new Date(0) ] },
                        1000 * 60 * 5
                    ]}
                ]},
                new Date(0)
            ]
        },
        "value": { "$first": "$value" }
    }}
])

基本原则是找到模($mod)或"余数"从时间开始,间隔为五分钟,并从基准时间中减去。这轮将在五分钟内完成。

当然另一部分是你$sort,以确保最小的原始"时间戳"排序"价值"在"顶部"。

其他部分是$subtract" epoch"将日期作为另一个日期的BSON日期,然后您会收到一个"整数"结果。类似的部分是添加($add)"整数"到BSON日期类型以接收另一个BSON日期。

结果是BSON Date对象四舍五入到您使用数学的区间。

  

1000毫秒X 60秒X 5分钟。