需要按小时聚合并且$ avg无法识别

时间:2015-11-13 23:27:02

标签: mongodb mongoose mongodb-query aggregation-framework

从存储带有时间戳的数据的MongoDB集合中,我需要为每小时返回一条记录。

到目前为止,我已成功选择了两个日期之间的记录集,但我无法确定如何在$group子句中构建我需要的每小时记录。

var myName = "CollectionName"
//schema for mongoose
var mySchema = new Schema({
    dt: Date,
    value: Number
});

var myDB = mongoose.createConnection('mongodb://localhost:27017/MYDB');

myDBObj = myDB.model(myName, evalSchema, myName);

此聚合调用中的匹配工作正常,$hour创建当天每小时的记录..但我不知道如何重新创建完整日期并获得错误{{1 } ...

"unknown group operator $avg"

我想我需要使用myDBObj.aggregate([ { $match: { "dt": { $gt: new Date("October 13, 2010 12:00:00"), $lt: new Date("November 13, 2010 12:00:00") } } },{ $group: { "_id": { "dt": { "$hour": "$dt" } , "price": { "$avg": "$price" }} }], function (err, data) { if (err) { return next(err); } res.json(data); }); 因此每天每小时都有不同的记录,并在某处包含$dayOfYear ...

有人可以帮我正确地做到这一点吗?任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:1)

$group管道阶段的工作原理是通过为_id指定的“密钥”对所有数据进行“分组”。您实际聚合的其他字段与_id值分开,并且是它们自己的字段属性。

所以你的$group会改为:

{ "$group": {
    "_id": { "$hour": "$dt" },
    "price": { "$avg": "$price" }
}}

或者,如果您希望按天打破,那么请复制一下密钥:

{ "$group": {
    "_id": { 
        "day": { "$dayOfYear": "$dt" },
        "hour": { "$hour": "$dt" }
    },
    "price": { "$avg": "$price" }
}}

或者只使用日期数学来生成按小时舍入的Date个对象:

{ "$group": {
    "_id": { 
        "$add": [
            { "$subtract": [
                { "$subtract": [ "$dt", new Date(0) ] },
                { "$mod": [
                    { "$subtract": [ "$dt", new Date(0) ] },
                    1000 * 60 *60
                ]}
            ]},
            new Date(0)
         ]
    },
    "price": { "$avg": "$price" }
}}

如果将另一个日期对象(纪元日期)从另一个日期对象中生成一个数值,您可以使用应用的数学运算(1000毫秒,60秒,60分钟= 1小时),并向日期对象添加数字会生成日期对应于该值。

所以你的问题是_id中的所有内容都无法识别$avg累加器。需要在分组键之外指定所有累加器。这就是意图。

如果你想将累加器值作为分组键的一部分(虽然这里似乎没有相关性),而是使用另一个组阶段,引用从前者生成的字段。