mongodb:当只有一个结果时,减少功能而不是动作

时间:2014-05-15 12:36:21

标签: mongodb

我需要做加权平均值。

编码如下

db.runCommand(
{ mapreduce : "<collecton>" ,
map: function ()
{
emit ({nkey: this.nkey}, {price: this.tags["31"], qty: this.tags["32"]});
},
reduce: function(key, vals)
{
var ret = {wavg:0};
var mul1 = 0.0;
var sum1 = 0.0;
for (var i=0;i<vals.length;i++)
{ mul1 += vals[i].price * vals[i].qty;
  sum1 += vals[i].qty;
}
ret.wavg = mul1/sum1;
return ret;
},
out: 'res2', verbose: true
}
);

> db.res2.find()
{ "_id" : { "nkey" : "key1" }, "value" : { "wavg" : 311.7647058823529 } }
{ "_id" : { "nkey" : "ke2" }, "value" : { "wavg" : 585.7142857142857 } }
{ "_id" : { "nkey" : "key3" }, "value" : { "price" : 1000, "qty" : 110 } }
{ "_id" : { "nkey" : "key4" }, "value" : { "wavg" : 825 } }

如果您注意到,在最终的reducer输出(第三行)中,它实际上通过reduce功能。密钥只出现一次,因此会发出一个结果。但是我仍然希望reduce函数能够根据它来获得加权平均值。我不能只在价格和数量上继续我只有一个密钥出现的地方,我也需要加权平均值。

有没有办法实现这个目标?

1 个答案:

答案 0 :(得分:0)

这实质上就是mapReduce的工作原理,当你只有一个结果时,永远不会调用reducer。但您可以随时使用finalize阶段改变此类结果:

db.runCommand({ 
    "mapreduce" : "<collecton>" ,
    "map": function () {
        emit (
            { "nkey": this.nkey}, 
            { "price": this.tags["31"], qty: this.tags["32"]}
        );
    },
    "reduce": function(key, vals) {
        var ret = { "wavg": 0 };
        var mul1 = 0.0;
        var sum1 = 0.0;

        for ( var i=0; i<vals.length; i++ ) { 
            mul1 += vals[i].price * vals[i].qty;
            sum1 += vals[i].qty;
        }

        ret.wavg = mul1/sum1;
        return ret;
    },
    "finalize": function(key,value) {
        if (value.hasOwnProperty("price") {
           value.wavg = value.price;
           delete value["price"];
        }

        return value;
    },
    "out": 'res2', 
    "verbose": true
});

或者以其他方式交替在reduce阶段加总你的钥匙,并在finalize阶段进行所有划分,如果这更符合你的想法。但是,你需要在“映射器”中进行“乘法”部分才能实现。