MongoDB - 对时间序列子文档进行范围查询

时间:2017-12-18 01:01:06

标签: mongodb time-series

我对Mongo很新,我只是围绕核心概念......我正在实施时间序列数据的模式,并且我打算尝试这里建议的模式:{ {3}},也出现在一些Mongo演讲中。

我理解架构,但我很难弄清楚如何在一系列日期中查询它。更具体地说,有人可以展示如何在上面的链接查询架构以检索跨越多个小时/天的1分钟系列的示例吗?理想情况下,无需在Mongo之外进行后期处理。

Mongo文档和聚合管道主要关注处理数组而不是嵌套的子文档...... TIA。

编辑:为了解决我试图解决的具体问题更加清晰......

我们假设我每隔1分钟存储一次数据,每天使用一个父文档,使用以下架构(从上面链接的帖子中剪断):

{
  timestamp_hour: ISODate("2013-10-10T23:00:00.000Z"),
  type: “spot_EURUSD”,
  values: {
    0: { 0: 1.2343, 1: 1.2343, …, 59: 1.2343},
    1: { 0: 1.2343, 1: 1.2343, …, 59: 1.2343},
    …,
    22: { 0: 1.2343, 1: 1.2343, …, 59: 1.2343},
    23: { 0: 1.2343, 1: 1.2343, …, 59: 1.2343}
  }
}

满足表单查询的最有效/最有效的方法是:"按时间顺序列出值,每分钟1个,​​从2013-09-25 1:37 pm开始,到结束时为止2013-10-15 at 2:56 pm"?

1 个答案:

答案 0 :(得分:1)

@jtromans对您提供的链接发表了评论,该评论应指向正确的方向:

  

...您应该继续“分类”您的数据,直至达到满足标准所需的最佳分辨率

假设你有一个如下的架构:

{
    timestamp_hour: ISODate(...),
    values: {
        0: {},
        1: {},
        ...
        59: {}
    }
}

然后你有一个每分钟的子文档,这将使你能够相当简单地满足你的查询(例如在第4分钟每次都找到,例如:

collection.find({}, {"values.3": 1})

这只是一个仅过滤您感兴趣的分钟值的投影。由于它是全表扫描,您可能希望在timestamp_hour字段中包含日期范围以限制搜索。如果您希望将值投影为更适合您期望的格式,则可以使用聚合,例如:

collection.aggregate([
    {$project: {val: "$values.1"}}
])

如果您需要能够在几小时,几秒或其他时间段内进行过滤,那么您需要使用框架或密钥来处理模式中的内容,例如:将秒和分钟合并:

{
    timestamp_hour: ISODate(...),
    minutes: {
        0: {
            seconds: {
                0: ...
            }
        },
        ...
    }
}

e.g。将其他值添加为键,以便对其进行索引和过滤:

{
    timestamp_hour: ISODate(...),
    hour_of_day: 0,
    day_of_month: 1
    minutes: {
        ...
    }
}

请注意,我在这里使用了每小时文档的方法,您必须根据您的数据和要求决定是否适合您,或者您是否需要每分钟,每天等文档。

编辑:这是一个更好地匹配编辑过的问题的示例:

db.ts.aggregate([
    {
        $match: {
            timestamp_hour: {$lte: {ISODate("2013-09-25")}, $gte: {ISODate("2013-10-15")}}
        }
    },
    {
        $project: {
            hours: {$objectToArray: "$values"}
        }
    },
    {
        $unwind: "$hours"
    },
    {
        $project: {
            hour_index: "$hours.k",
            minutes: {$objectToArray: "$hours.v"}
        }
    },
    {
        $unwind: "$minutes"
    },
    {
        $project: {
            reconstructed_date: {$dateFromParts: {
                year: {$year: "$timestamp_hour"},
                month: {$month: "$timestamp_hour"},
                day: {$day: "$timestamp_hour"},
                hour: "$hour_index",
                minute: "$minutes.k",
            }}
            value: "$minutes.v"
        }
    },
    {
        $match: {
            reconstructed_date: {$lte: {ISODate("2013-09-25T13:37:00.000Z")}, $gte: {ISODate("2013-10-15T14:56:00.000Z")}}
        }
    }
])

我并没有试图在这个时间区域获得时区,这取决于你!