MongoDB:有没有一种方法可以使用聚合来检测价值趋势? [英] MongoDB : Is there a way to detect a value trend using aggregation?

查看:76
本文介绍了MongoDB:有没有一种方法可以使用聚合来检测价值趋势?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试检测集合中某个值的趋势".

I'm trying to detect the "trend" of a value in a collection.

假设我有以下内容:

{ created_at: 2014-12-01, value:1015 }
{ created_at: 2014-12-01, value:1015 }
{ created_at: 2014-12-01, value:1019 }
{ created_at: 2014-12-02, value:1018 }
{ created_at: 2014-12-02, value:1021 }
{ created_at: 2014-12-03, value:1010 }
{ created_at: 2014-12-03, value:1012 }
{ created_at: 2014-12-03, value:1011 }
{ created_at: 2014-12-04, value:1012 }

我只想要一个输出,如:

I just want to have an output like:

{ created_at: 2014-12-01, average: 1016, diff: 0}
{ created_at: 2014-12-02, average: 1019, diff: 3}

其中diff是平均值之间的差 这两个日期.

With diff being the difference of the average value between the two dates.

我想出了如何计算平均值,查找集合中的最小/最大值和第一个/最后一个值,但是找不到比较两个平均值的方法...

I figured out how to calculate the averages, find min/max and first/last values in the collection, but can't find a way to compare the two averages...

推荐答案

根据您对每分钟汇总"的评论,假设这些是实际日期,唯一一次通过此操作的真正方法是使用mapReduce.这里的关键是mapReduce可以存储全局变量,因此可以跟踪"您的最后结果以确定每个聚合记录之间的差异"

Presuming these are actual dates according to your comments on "aggregate per minute" the only real way to do this in a single pass is using mapReduce. The key here is that mapReduce can store a global variable and therefore "track" your last result in order to determine the "difference" between each aggregated record

db.collection.mapReduce(
    function() {
        // Round date to the minute
        var key = this.created_at.valueOf()
            - ( this.created_at.valueOf() % ( 1000 * 60 ) );
        emit( key, { "average": this.value } );
    },
    function(key,values) {
        values = values.map(function(i) { return i.average });
        var result = {
           "average": Math.floor(Array.avg(values))
        };
        return result;
    },
    {
        "out": { "inline": 1 },
        "scope": { "lastAvg": 0 },
        "finalize": function(key,value) {
            value.diff = ( lastAvg == 0 ) ? 0 : value.average - lastAvg;
            lastAvg = value.average;
            return value;
        }
    }
)

或者,您可以像前面提到的那样对后处理"进行处理",并在客户端代码中执行相同的操作,以在使用类似范围变量迭代游标时计算差异.作为外壳示例:

Alternately you can "post-process" as has been mentioned and do the same thing in your client code to calculate the difference as you iterate the cursor with a similar scoped variable. As a shell example:

var lastAvg = 0;
db.collection.aggregate([
    { "$group": {
        "_id": { "$subtract": [
            { "$subtract": [ "$created_date", new Date(0) ] },
            { "$mod": [
                { "$subtract": [ "$created_date", new Date(0) ] },
                1000 * 60
            ]}
        ]},
        "average": { "$avg": "$value" }
    }},
    { "$sort": { "_id": 1 } }
]).forEach(function(doc) {
    doc.average = Math.floor(doc.average);
    doc.diff = ( lastAvg == 0 ) ? 0 : doc.average - lastAvg;
    lastAvg = doc.average;
    printjson(doc);
})

在两种情况下,我都使用日期数学原理将日期对象转换为unix/epoch时间戳表示形式,该数字以分钟为单位四舍五入到最接近的下限.使用聚合框架,您可以替代地使用日期聚合运算符提取分组的日期部分.

In both cases there I am using the date math principles in order to convert the date object into a unix/epoch timestamp representation as a number which is rounded out to it's nearest floor by minute. With the aggregation framework you could alternately use the date aggregation operators to extract the date parts for grouping.

无论哪种情况,将其重新转换为Date对象都是非常简单的,需要在内部使用.mapReduce()进行转换,或在使用.aggregate()的后期处理中进行.

In either case it's really simple to re-cast that as a Date object where required either internally with .mapReduce() or in post processing using .aggregate().

因此,在总结中,您可以使用mapReduce的全局范围"功能,也可以只处理汇总中的结果游标,以计算出结果中每个分组之间的差异.

So in wrap up, you can either use the "global scope" functionality of mapReduce or you can just process the resulting cursor from aggregate in order to work out the differences between each grouping in results.

这篇关于MongoDB:有没有一种方法可以使用聚合来检测价值趋势?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆