MongoDB 汇总时间序列
MongoDB Aggregate Time Series
我正在使用 MongoDB 使用与 "The Document-Oriented Design" 类似的结构存储时间序列数据,此处解释如下:http://blog.mongodb.org/post/65517193370/schema-design-for-time-series-data-in-mongodb
objective是查询全系统一天中最忙的前10分钟。每个文档使用 60 个子文档(每分钟 1 个)存储 1 小时的数据。每分钟存储嵌入在 "vals" 字段中的各种指标。我关心的指标是 "orders"。示例文档如下所示:
{
"_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 来完成,但我不确定如何。
您可以汇总为:
$match
特定日期的文档。
- 查询前构造
$group
和$project
对象。
$group
由$hour
,累计每小时所有文件
array.Keep 文档中某处的分钟。
$project
一个变量文档作为每个文档的 $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"}}
])
我正在使用 MongoDB 使用与 "The Document-Oriented Design" 类似的结构存储时间序列数据,此处解释如下:http://blog.mongodb.org/post/65517193370/schema-design-for-time-series-data-in-mongodb
objective是查询全系统一天中最忙的前10分钟。每个文档使用 60 个子文档(每分钟 1 个)存储 1 小时的数据。每分钟存储嵌入在 "vals" 字段中的各种指标。我关心的指标是 "orders"。示例文档如下所示:
{
"_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 来完成,但我不确定如何。
您可以汇总为:
$match
特定日期的文档。- 查询前构造
$group
和$project
对象。 $group
由$hour
,累计每小时所有文件 array.Keep 文档中某处的分钟。$project
一个变量文档作为每个文档的$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"}}
])