Node.js 带循环的MongoDB聚合管道

Node.js 带循环的MongoDB聚合管道,node.js,mongodb,mongodb-query,aggregation-framework,Node.js,Mongodb,Mongodb Query,Aggregation Framework,下面是我想要在一年中的每一天运行的聚合管道代码!基本上计算一年中每天的最低、最高和平均温度场。目前,我调用这段代码365次,传递一天的开始日期和结束日期 显然,这是非常低效的。是否有任何方法可以在mongo中循环此操作,以使其更快,并返回一个包含365个平均值、365个最小值和365个最大值或类似值的数组。我使用时区库来推导开始日期和结束日期 collection.aggregate([ { $match:{$and:[ {"UID" : uid},

下面是我想要在一年中的每一天运行的聚合管道代码!基本上计算一年中每天的最低、最高和平均温度场。目前,我调用这段代码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")}
....
有什么想法吗?也许我们可以在聚合管道中传递一年中所有日子的所有时间戳


谢谢

既然可以简单地将日期作为分组键的一部分,为什么每天都要运行此命令?这就是exist的目的,因此您可以一次在整个时段内按时间帧进行聚合,而无需循环:

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" }
    }}
])
当然,这里的日期范围现在是您需要在结果中显示的所有日期,因此您希望循环的所有内容的开始日期和结束日期。无论哪种情况,分组都是为了反映一天,但当然,您可以将其更改为您想要的任何时间间隔


还请注意,您不需要使用here。默认情况下,MongoDB中的查询和条件。您唯一需要该运算符的时间是针对同一字段上的多个条件,否则这些条件将是无效的JSON/BSON。

Hi Neil,谢谢!关于时区会发生什么?如果我使用内置的$dayOfMonth,$week操作符,是否有调整时区的最佳实践?好的,确实时区功能尚未实现。跟踪:我想,由于夏令时等原因,即使在查询中添加偏移量也不会有多大帮助。