我正在使用下面的聚合管道代码,我想在一年中的每一天运行!基本上计算一年中每一天的最低,最高和平均温度(" TEMP"字段)。目前我正在调用这段代码365次,传递一天的开始日期和结束日期。
显然这是非常低效的。有没有办法在mongo中循环这个以便它更快,并返回一个365平均值,365分钟值和365最大值或类似的数组。我使用时区库来导出开始日期和结束日期。
collection.aggregate([
{
$match:{$and:[
{"UID" : uid},
{"TEMP" :{$exists:true}}
{"site" : "SITE123"},
{"updatedAt": {$gte : new Date(START_DATE_ARG), $lte : new Date(END_DATE_ARG)} }
]}
},
{ "$group": {
"_id": "$UID",
"avg": { $avg: $TEMP },
"min": { $min: $TEMP },
"max": { $max: $TEMP }
}
}
], function(err, result){
if (err){
cb(1, err);
}
else{
cb(0, result);
}
});
});
数据集看起来像这样
....
{UID: "123", TEMP: 11, site: "SITE123", updatedAt: ISODate("2014-09-12T21:55:19.326Z")}
{UID: "123", TEMP: 10, site: "SITE123", updatedAt: ISODate("2014-09-12T21:55:20.491Z")}
....
有什么想法吗?也许我们可以在聚合管道中传递一年中所有日期的所有时间戳?
谢谢!!
答案 0 :(得分:0)
为什么只需将日期作为分组键的一部分,每天运行一次?这就是date aggregation operators的存在,因此您可以在一段时间内按时间帧聚合而不循环:
collection.aggregate([
{ "$match":{
"UID": uid,
"TEMP":{ "$exists": true }
"site" : "SITE123",
"updatedAt": {
"$gte": new Date(START_DATE_ARG),
"$lte": new Date(END_DATE_ARG)
}}
}},
{ "$group": {
"_id": {
"uid": "$UID",
"year": { "$year": "$updatedAt" },
"month": { "$month": "$updatedAt" },
"day": { "$dayOfMonth" }
},
"avg": { "$avg": "$TEMP" },
"min": { "$min": "$TEMP" },
"max": { "$max": "$TEMP" }
}}
])
或者可能只是将日期缩小为时间戳值。日期对象的日期数学小技巧:
collection.aggregate([
{ "$match":{
"UID": uid,
"TEMP":{ "$exists": true }
"site" : "SITE123",
"updatedAt": {
"$gte": new Date(START_DATE_ARG),
"$lte": new Date(END_DATE_ARG)
}}
}},
{ "$group": {
"_id": {
"uid": "$UID",
"date": {
"$subtract": [
{ "$subtract": [ "$updatedAt", new Date("1970-01-01") ] },
{ "$mod": [
{ "$subtract": [ "$updatedAt", new Date("1970-01-01") ] },
1000 * 60 * 60 * 24
]}
]
}
},
"avg": { "$avg": "$TEMP" },
"min": { "$min": "$TEMP" },
"max": { "$max": "$TEMP" }
}}
])
当然,您的“日期范围”现在是所有您需要在结果中显示的日期,因此您打算循环的所有内容的开始日期和结束日期。分组在两种情况下完成以反映“一天”,但当然您可以将其更改为您想要的任何间隔。
另请注意,您无需在此处使用$and
。默认情况下,查询MongoDB“和”条件。您需要该运算符的唯一时间是在同一字段上的多个条件,否则将无效JSON / BSON。