MongoDB聚合时间序列

Posted

技术标签:

【中文标题】MongoDB聚合时间序列【英文标题】:MongoDB Aggregate Time Series 【发布时间】:2015-02-03 22:47:23 【问题描述】:

我正在使用 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 完成,但我不确定如何。

【问题讨论】:

【参考方案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 次太多,但这个概念本身是有效的。谢谢!

以上是关于MongoDB聚合时间序列的主要内容,如果未能解决你的问题,请参考以下文章

使用聚合管道聚合 MongoDB 中的时间戳集合

如何在 MongoDB 中聚合时间序列数据

MongoDB慢聚合时间

MongoDB 时间序列聚合

带有大量文档的 MongoDb 聚合查找?

带有大量文档的 MongoDb 聚合查找?