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
文件。
$sort
orders
$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聚合时间序列的主要内容,如果未能解决你的问题,请参考以下文章