首页 > 解决方案 > 对不同时间戳的时间序列求和 MongoDB

问题描述

我有一个包含多个时间序列数据的 mongoDB 数据库,每个时间戳都是一个单独的文档,其中包含来自传感器的一些附加元数据。我想在一个聚合中总结两个时间序列,但我为此苦苦挣扎,找不到任何例子。

假设我们有传感器 A 和 B,并且来自不同传感器的时间戳不对齐。请参阅下面的数据示例。接下来我想总结两个时间序列的“体积”指标。因此,对于下面的示例,传感器 A 有两个时间戳和传感器 B 3。因此,A 和 B 的总和应该有 5 个时间戳,这样总和就会反映总体积的所有变化(另请参见下面的示意图示例)。

任何人都知道如何在 mongoDB 聚合查询中解决这个问题?我只能使用 mongoDB 查询语言而不能使用 NodeJS。

传感器 A

{
"_id":5d67d9ee074e99274eef30d5
"sensor": A
"volume":12.4
"temperatue": 20
"timestamp":2019-08-29 15:58:06.093
"__v":0
}

{
"_id":5d67da66074e99274eef30ea
"sensor": A
"volume":12.3
"temperatue": 21
"timestamp":2019-08-29 16:48:06.078
"__v":0
}

..etc

传感器 B

{
"_id":5d67d9ee074e99274eef30d5
"sensor": B
"volume":32.4
"temperatue": 20
"timestamp":2019-08-29 15:55:06.093
"__v":0
}

{
"_id":5d67da66074e99274eef30ea
"sensor": B
"volume":21.2
"temperatue": 21
"timestamp":2019-08-29 16:49:06.178
"__v":0
}

{
"_id":5d67da66074e99274eef30ea
"sensor": B
"volume":22.3
"temperatue": 22
"timestamp":2019-08-29 17:04:06.078
"__v":0
}

..etc

这里也是我想要的结果的草图。

在此处输入图像描述

标签: mongodbmongodb-query

解决方案


试试这个:

db.collection.aggregate([
  // Determine start and end-time
  { $sort: { timestamp: -1 } },
  { $group: { _id: "$sensor", data: { $push: "$$ROOT" } } },
  {
    $set: {
      data: {
        $reduce: {
          input: "$data",
          initialValue: [],
          in: {
            $concatArrays: [
              "$$value",
              [
                {
                  $mergeObjects: [
                    "$$this",
                    {
                      timestamp_end: {
                        $ifNull: [ { $last: "$$value.timestamp" }, "$$NOW" ]
                      }
                    }
                  ]
                }
              ]
            ]
          }
        }
      }
    }
  },
  { $unwind: "$data" },
  // find data per interval
  { $sort: { "data.timestamp": 1 } },
  {
    $group: {
      _id: null,
      data: { $push: "$data" },
      timestamp: { $addToSet: "$data.timestamp" }
    }
  },
  {
    $set: {
      sum_data: {
        $map: {
          input: "$timestamp",
          as: "t",
          in: {
            $filter: {
              input: "$data",
              cond: {
                $and: [
                  { $lte: [ "$$this.timestamp", "$$t" ] },
                  { $gt: [ "$$this.timestamp_end", "$$t" ] }
                ]
              }
            }
          }
        }
      }
    }
  },
  // sum up temperatures
  {
    $set: {
      volume: {
        $map: {
          input: "$sum_data",
          in: { $sum: "$$this.volume" }
        }
      },
      result: { $range: [ 0, { $size: "$timestamp" } ] }
    }
  },
  // Join arrays to final result
  {
    $project: {
      result: {
        $map: {
          input: "$result",
          as: "i",
          in: { 
            timestamp: { $arrayElemAt: [ "$timestamp", "$$i" ] },
            volume: { $arrayElemAt: [ "$volume", "$$i" ] }
          }
        }
      }
    }
  }
])

蒙戈游乐场


推荐阅读