我需要做加权平均值。
编码如下
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函数能够根据它来获得加权平均值。我不能只在价格和数量上继续我只有一个密钥出现的地方,我也需要加权平均值。
有没有办法实现这个目标?
答案 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
阶段进行所有划分,如果这更符合你的想法。但是,你需要在“映射器”中进行“乘法”部分才能实现。