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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MongoDB - 对时间序列子文档进行范围查询相关的知识,希望对你有一定的参考价值。

我是Mongo的新手,我只是围绕核心概念......我正在实现时间序列数据的模式,并且我打算尝试这里建议的模式:MongoDB as a Time Series Database,它也出现在一些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开始,到2013-10-15结束下午2点56“?

答案

@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: ...
            }
        },
        ...
    }
}

例如将其他值添加为键,以便对其进行索引和过滤:

{
    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")}}
        }
    }
])

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

以上是关于MongoDB - 对时间序列子文档进行范围查询的主要内容,如果未能解决你的问题,请参考以下文章

我可以对索引子文档字段执行 MongoDB“开始于”查询吗?

mongodb查询以将子文档显示为主文档并使用它进行分页

MongoDB 集合间关联查询后通过$filter进行筛选

MongoDB 查询子文档数组

spirng集成Mongodb Criteria 进行子文档查询

Mongodb:按元素分组并根据条件显示子文档计数并按日期对文档进行排序