如何使用mongodb聚合?

时间:2015-10-31 10:17:48

标签: mongodb mongodb-query aggregation-framework

我有一个这样的集合:

{'speed':45, 'time':1446271000},   
{'speed':45, 'time':1446271001},   
{'speed':63, 'time':1446271002},    
{'speed':68, 'time':1446271003},  
{'speed':70, 'time':1446271004},    
{'speed':59, 'time':1446271005},   
{'speed':55, 'time':1446271006},    
{'speed':61, 'time':1446271007},    
{'speed':62, 'time':1446271008},   
{'speed':63, 'time':1446271009},    
{'speed':67, 'time':1446271010}   

我想总结高速(速度> = 60)记录,因此结果应如下所示:

{'speed':63,'duration':2,'start': 1446271002,'end': 1446271004}  
{'speed':61,'duration':3,'start': 1446271007,'end': 1446271010}

我该如何实现这个目标?

2 个答案:

答案 0 :(得分:2)

使用以下聚合管道执行初始 $match 来过滤掉小于60的文档。

下一个管道步骤使用 $sort 运算符按时间字段重新排序文档,这是下一步所必需的,即 $group 管道。在这里,您可以通过使用 $first $last 累加器运算符来获取开始和结束字段。第一次和最后一次按速度字段对文档进行分组作为键。

最后一个管道步骤 $project 使用 $subtract 算术运算符创建附加字段,持续时间,顾名思义,它减去来自start次的end。最终的管道如下所示:

db.test.aggregate([
    { "$match": { "speed": { "$gte": 60 } } },
    { "$sort": { "time": 1 }  },
    {
        "$group": {
            "_id": "$speed",
            "start": { "$first": "$time" },
            "end": { "$last": "$time" }
        }
    },
    {
        "$project": {
            "_id": 0,
            "speed": "$_id",
            "duration": { "$subtract": [ "$end", "$start" ] },
            "start": 1,
            "end": 1
        }
    }
])

示例输出:

/* 0 */
{
    "result" : [ 
        {
            "start" : 1446271010,
            "end" : 1446271010,
            "speed" : 67,
            "duration" : 0
        }, 
        {
            "start" : 1446271007,
            "end" : 1446271007,
            "speed" : 61,
            "duration" : 0
        }, 
        {
            "start" : 1446271008,
            "end" : 1446271008,
            "speed" : 62,
            "duration" : 0
        }, 
        {
            "start" : 1446271004,
            "end" : 1446271004,
            "speed" : 70,
            "duration" : 0
        }, 
        {
            "start" : 1446271003,
            "end" : 1446271003,
            "speed" : 68,
            "duration" : 0
        }, 
        {
            "start" : 1446271002,
            "end" : 1446271009,
            "speed" : 63,
            "duration" : 7
        }
    ],
    "ok" : 1
}

答案 1 :(得分:0)

我发布这个是因为现有的答案会向管道添加不必要的$sort阶段,这将导致性能下降。

您需要使用$gte运算符过滤掉speed$match的集合中的所有文档,然后按“速度”过滤$group您的文档并使用{ {3}}和$min累加器运算符分别返回不同组的“时间”的最小值和最大值。从那里你需要$max离子阶段使用$project运算符来计算“持续时间”。当然,$subtract方法可以访问.aggregate()

db.collection.aggregate([ 
    { "$match": { 
        "speed": { "$gte": 60 } 
    }}, 
    { "$group": { 
        "_id": "$speed", 
        "duration": { "$sum": 1 }, 
        "start": { "$min": "$time" }, 
        "end": { "$max": "$time" }
    }},
    { "$project": { 
        "speed": "$_id", 
        "_id": 0, 
        "duration": { "$subtract": [ "$end", "$start" ] }, 
        "start": 1, 
        "end": 1 
    }} 
])

哪个收益率:

{ "start" : 1446271010, "end" : 1446271010, "speed" : 67, "duration" : 0 }
{ "start" : 1446271008, "end" : 1446271008, "speed" : 62, "duration" : 0 }
{ "start" : 1446271007, "end" : 1446271007, "speed" : 61, "duration" : 0 }
{ "start" : 1446271004, "end" : 1446271004, "speed" : 70, "duration" : 0 }
{ "start" : 1446271003, "end" : 1446271003, "speed" : 68, "duration" : 0 }
{ "start" : 1446271002, "end" : 1446271009, "speed" : 63, "duration" : 7 }