【问题标题】:MongoDB Aggregate Time SeriesMongoDB聚合时间序列
【发布时间】:2023-03-07 12:41:01
【问题描述】:

我正在使用 MongoDB 来存储时间序列数据,其结构与此处解释的“面向文档的设计”类似:http://blog.mongodb.org/post/65517193370/schema-design-for-time-series-data-in-mongodb

目标是查询整个系统一天中最繁忙的 10 分钟。每个文档使用 60 个子文档(每分钟 1 个)存储 1 小时的数据。每分钟存储嵌入在“vals”字段中的各种指标。我关心的指标是“订单”。示例文档如下所示:

{
        "_id" : ObjectId("54d023802b1815b6ef7162a4"),
        "user" : "testUser",
        "hour" : ISODate("2015-01-09T13:00:00Z"),
        "vals" : {
                "0" : {
                        "orders" : 11,
                        "anotherMetric": 15
                },
                "1" : {
                        "orders" : 12,
                        "anotherMetric": 20
                },
                .
                .
                .
        }
}

请注意,系统中有很多用户。

我已经设法通过使用以下组对象进行聚合来(在某种程度上)扁平化结构:

group = {
    $group: {
        _id: {
            hour: "$hour"
        },
        0: {$sum: "$vals.0.orders"},
        1: {$sum: "$vals.1.orders"},
        2: {$sum: "$vals.2.orders"},
        .
        .
        .
    }
}

但这只会给我 24 个文档(每小时 1 个)以及该小时内每分钟的订单数,如下所示:

{
    "_id" : {
            "hour" : ISODate("2015-01-20T14:00:00Z")
    },
    "0" : 282086,
    "1" : 239358,
    "2" : 289188,
    .
    .
    .
}

现在我需要以某种方式从中获得一天中前 10 分钟的时间,但我不确定如何。我怀疑它可以用 $project 完成,但我不确定如何。

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    你可以聚合为:

    • $match特定日期的文件。
    • 在查询之前构造$group$project 对象。
    • $group by $hour,每小时累积所有文件 数组中的分钟。将分钟保存在文档中的某个位置。
    • $project 一个变量 docs 作为 $setUnion 的所有文档 小时。
    • $unwind 文件。
    • $sortorders
    • $limit 最上面的10 文件,这是我们需要的。

    代码:

    var inputDate = new ISODate("2015-01-09T13:00:00Z");
    var group = {};
    var set = [];
    for(var i=0;i<=60;i++){
        group[i] = {$push:{"doc":"$vals."+i,
                           "hour":"$_id.hour",
                           "min":{$literal:i}}};
        set.push("$"+i);
    }
    group["_id"] = {$hour:"$hour"};
    var project = {"docs":{$setUnion:set}}
    
    db.t.aggregate([
    {$match:{"hour":{$lte:inputDate,$gte:inputDate}}},
    {$group:group},
    {$project:project},
    {$unwind:"$docs"},
    {$sort:{"docs.doc.orders":-1}},
    {$limit:2},
    {$project:{"_id":0,
               "hour":"$_id",
               "doc":"$docs.doc",
               "min":"$docs.min"}}
    ])
    

    【讨论】:

    • 这个策略做到了。你的 for 循环重复了 1 次太多,但这个概念本身是有效的。谢谢!
    猜你喜欢
    • 2015-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多