【问题标题】:Mongo 3.2 query timeseries value at specific timeMongo 3.2 查询特定时间的时间序列值
【发布时间】:2017-08-06 15:39:44
【问题描述】:

我有一些时间序列数据存储在 Mongo 中,每个帐户一个文档,如下所示:

{
    "account_number": 123,
    "times": [
         datetime(2017, 1, 2, 12, 34, 56),
         datetime(2017, 3, 4, 17, 18, 19),
         datetime(2017, 3, 11, 0, 1, 11),
    ]
    "values": [
         1,
        10,
       9001,
    ]
}

因此,要明确在上述表示帐户123 的值从2017-01-02 12:34:56 变为1,直到它在2017-03-04 17:18:19 上变为10,然后在2017-03-11, 00:01:11 上变为9001

有许多帐户,每个帐户的数据都不同(可能在不同的时间,并且可能比其他帐户具有更多或更少的值变化)。

我想在给定时间查询每个用户的价值,例如"2017-01-30 02:03:04 的每个用户的价值是多少?将返回上述帐户的1,因为它在给定时间之前设置为1,并且直到给定时间之后才改变。

看起来$zip 会很有用,但这仅在 Mongo 3.4 中可用,我正在使用 3.2,并且没有计划很快升级。

编辑:

我可以使用以下方法到达那里的一小部分:

> db.account_data.aggregate([{$unwind: '$times'}, {$unwind: '$values'}])

返回类似:

{"account_number": 123, "times": datetime(2017, 1, 2, 12, 34, 56), "values": 1},
{"account_number": 123, "times": datetime(2017, 1, 2, 12, 34, 56), "values": 10},
#...

这不太正确,因为它返回时间/值的叉积

【问题讨论】:

  • 更新架构是否适合您?如果您可以将它们作为嵌入数组中的键值对,它将对您有所帮助。
  • 仅使用 MongDB 3.2 功能查看我的答案

标签: mongodb mongodb-query time-series


【解决方案1】:

仅使用 3.2 功能就可以做到这一点。我用Mingo 库测试过

var mingo = require('mingo')

var data = [{
    "account_number": 123,
    "times": [
        new Date("2017-01-02T12:34:56"),
        new Date("2017-03-04T17:18:19"),
        new Date("2017-03-11T00:01:11")
    ],
    "values": [1, 10, 9001]
}]

var maxDate = new Date("2017-01-30T02:03:04")

// 1. filter dates down to those less or equal to the maxDate
// 2. take the size of the filtered date array
// 3. subtract 1 from the size to get the index of the corresponding value
// 4. lookup the value by index in the "values" array into new "valueAtDate" field
// 5. project the extra fields
var result = mingo.aggregate(data, [{
    $project: {
        valueAtDate: {
            $arrayElemAt: [
                "$values",
                { $subtract: [ { $size: { $filter: { input: "$times", as: "time", cond: { $lte: [ "$$time", maxDate ] }} } }, 1 ] }
            ]
        },
        values: 1,
        times: 1
    }
}])

console.log(result)

// Outputs
[ { valueAtDate: 1,
    values: [ 1, 10, 9001 ],
    times:
    [ 2017-01-02T12:34:56.000Z,
    2017-03-04T17:18:19.000Z,
    2017-03-11T00:01:11.000Z ] } ]

【讨论】:

    【解决方案2】:

    不确定如何对MongoDb 3.2 执行相同操作,但是从3.4 您可以执行以下查询:

    db.test.aggregate([
    {
        $project:
          {
            index: { $indexOfArray: [ "$times", "2017,3,11,0,1,11" ] },
            values: true
          }
    },
    {
      $project: {
        resultValue: { $arrayElemAt: [ "$values", "$index" ] }
      }
    }])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-02
      • 2022-01-17
      • 2016-06-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多