使用复合键进行聚合

时间:2015-09-29 11:19:28

标签: mongodb mongodb-query aggregation-framework

我正在尝试聚合一些数据并按时间间隔对其进行分组以及维护子类别,如果愿意的话。我希望能够将这些数据绘制出来,这样我就会有多个不同的行对应于每个被调用的Office。 X轴是时间间隔,Y轴是平均振铃时间。

我的数据如下:

 Calls: [{
    created: ISODate(xyxyx), 
    officeCalled: 'ABC Office', 
    answeredAt: ISODate(xyxyx)
    },
    {
    created: ISODate(xyxyx), 
    officeCalled: 'Office 2', 
    answeredAt: ISODate(xyxyx)
    },
    {
    created: ISODate(xyxyx), 
    officeCalled: 'Office 3', 
    answeredAt: ISODate(xyxyx)
    }];

我的目标是按时间间隔(30分钟/ 1小时/ 1天)和被叫办公室分组。所以当我的聚合完成时,我正在寻找这样的数据:

[{"_id":TimeInterval1,"calls":[{"office":"ABC Office","ringTime":30720},
            {"office":"Office2","ringTime":3070}]}, 
 {"_id":TimeInterval2,"calls":[{"office":"Office1","ringTime":1125},
            {"office":"ABC Office","ringTime":15856}]}] 

过去几个小时我一直在四处寻找,我能够汇总我的数据,但我还没弄清楚如何正确分组,以便每个时间间隔都与办公室数据一起。这是我最新的代码:

Call.aggregate([
{$match: {
    $and: [
        {created: {$exists: 1}}, 
        {answeredAt: {$exists: 1}}]}},
{$project: {    created: 1, 
            officeCalled: 1, 
        answeredAt: 1,  
        timeToAns: {$subtract: ["$answeredAt", "$created"]}}},

{$group: {_id: {"day": {"$dayOfYear": "$created"},

        "hour": {
            "$subtract": [
                {"$hour" : "$created"}, 
                {"$mod": [ {"$hour": "$created"}, 2]}
                ]
        }, 
                "officeCalled": "$officeCalled"

 }, 
    avgRingTime: {$avg: '$timeToAns'}, 
    total: {$sum: 1}}},

{"$group": {
        "_id": "$_id.day", 
        "calls": {
            "$push": {
                "office": "$_id.officeCalled", 
                "ringTime": "$avgRingTime"

            }, 

        }
    }}, 
 {$sort: {_id: 1}}


]).exec(function(err, results) {
    //My results look like this

     [{"_id":118,"calls":[{"office":"ABC Office","ringTime":30720}, 
       {"office":"Office 2","ringTime":31384.5},
       {"office":"Office 3","ringTime":7686.066666666667},...];

      });

这只是不太明白......我得到了我的数据,但它只按天来分解。不是我拍摄的2小时时间间隔。请告诉我,如果我这样做完全错了,请 - 我对汇总非常新,所以非常感谢您的帮助。

谢谢!

1 个答案:

答案 0 :(得分:2)

您真正需要做的就是在最终组中包含您想要的_id值的两个部分。不知道为什么你认为只引用一个字段。

同时"松开$project"因为它只是浪费了周期和处理,当你可以在第一次尝试时直接在$group中使用:

Call.aggregate(
    [
        { "$match": {
            "created": { "$exists": 1 },
            "answeredAt": { "$exists": 1 }
        }},
        { "$group": {
            "_id": {
                "day": {"$dayOfYear": "$created"},
                "hour": {
                    "$subtract": [
                        {"$hour" : "$created"}, 
                        {"$mod": [ {"$hour": "$created"}, 2]}
                    ]
                }, 
                "officeCalled": "$officeCalled"

            }, 
            "avgRingTime": { 
                "$avg": { "$subtract": [ "$answeredAt", "$created" ] }
            }, 
            "total": { "$sum": 1 }
        }},
        { "$group": {
            "_id": { 
                "day": "$_id.day",
                "hour": "$_id.hour"
            }, 
            "calls": {
                "$push": {
                    "office": "$_id.officeCalled", 
                    "ringTime": "$avgRingTime"
                }, 
            },
            "total": { "$sum": "$total" }
        }},
        { "$sort": { "_id": 1 } }
    ]
).exec(function(err, results) {

});

另请注意$and完全遗漏。这不是必需的,因为所有 MongoDB查询参数已经是" AND"无论如何,条件,除非另有说明。坚持简单。这很简单。