计算MapReduce中最后X个文档的平均值

时间:2015-06-27 18:02:07

标签: javascript node.js mongodb mapreduce mongoose

我甚至知道mapreduce是否是我需要的最佳选择。我有一个像这样的猫鼬文件:

currency { 
   Time: Date,
   Interval: Number
}

在我的mapreduce作业中,我想计算最后X个文档的平均价格(间隔)。 (包括当前)。

如果我将20传递给我的方法,我想要每个文档,计算最后19 +当前值的值除以20。 任何有关正确方向的建议或指示都将受到赞赏。这就是我想要实现的目标:

function calculateAverages(Schema, interval, avg, callback){
    v
    var o = {};
    o.scope = {interval: interval, avg: avg};

    o.map = function(){

            var value = {
                  Time: this.Date,
                  Interval: this.Interval

            };

            // How am I gonna group the correct number of docs togheter?
            var key= ??

            emit(key, value);


    };
    //  an array of avg ( ex 20) number of items should be passed here
    o.reduce = function(key, intervals){
            var reducedVal = { avg: 0};

            for(var i=0;i<intervals.length;i++){
                reducedVal.avg += intervals[i].Interval;
            }
        reducedVal.avg /= avg;
        return reducedVal;
    };

    o.out = {
      merge: "testing"
    };
    o.finalize = function(key, reducedVal){
        return reducedVal;
    };

    Schema.mapReduce(o, function (err, results) {
        if (err) throw err;

        //console.log(results);
        console.log("mapReduce complete");

        callback(results);
    });
};

2 个答案:

答案 0 :(得分:1)

您可以使用简单的聚合管道来获得平均值,pipline将遵循此步骤

  1. 按时间字段对文档进行排序
  2. 限制文件数
  3. 对文件进行分组并获得平均值
  4. 您可以尝试下面的代码,它只是创建货币模型并向mongodb发送聚合查询,结果显示在控制台上,您的收藏应该是mongodb服务器上的nammed货币。

    var mongoose = require('mongoose');
    var db = mongoose.connection;
    mongoose.connect('mongodb://localhost/test');
    
    var CurrencySchema = mongoose.Schema({
        Time: Date,
        Interval: Number
    }, {collection: 'currency'});
    
    var Currency = mongoose.model('Currency', CurrencySchema);
    // You can change the $limit to specify the number of document
    
    db.once('open', function (callback) {
      var pipeline = [
        {$sort: {Time : -1 }},
        {$limit: 5},
        {$group: {_id: null, average : {$avg: "$Interval"}}}
      ];
    
      Currency.aggregate(pipeline).exec(function(err, data) {
         console.log(data);
      });
    });
    

答案 1 :(得分:0)

如果你想继续使用MapReduce,我的第一种方法是使用“GROUP”+ X作为键,其中X是每组后增加的数值。在你可以访问的任何地方声明n = 1并用n ++递增它,当n%avg = 0时,在你的发射之后X ++ / n = 1

很抱歉,如果我用Java键入我的示例,那就是我使用MapReduce的语言。但我认为你很容易理解我的方法:

private int X = 1, n=1;

public map(Text anyKey, YourStructure value){
    int avg = ....; //Recover your avg value here, wherever it is stored.
    emit("GROUP"+X, value);
    if (n % avg == 0){
        X++;
        n=1;
    }else{
        n++;
    }
}

你发出:

Doc 1 --> key: GROUP1, value: {.....}
Doc 2 --> key: GROUP1, value: {.....}
...
Doc 19 --> key: GROUP1, value: {.....}
Doc 20 --> key: GROUP1, value: {.....}

Doc 21 --> key: GROUP2, value: {.....}
Doc 22 --> key: GROUP2, value: {.....}
...
Doc 29 --> key: GROUP2, value: {.....}
Doc 30 --> key: GROUP2, value: {.....}

Doc 31 --> key: GROUP3, value: {.....}
...

通过这种方式,您可以在reduce中获得所需的文档数量,以计算平均价格。

希望这会对你有所帮助。