不知道大家有没有遇到过,使用mapreduce其中需要计数记录数的时候,我们在reduce中使用 number = number + 1 发现统计的出来的数量往往小于我们希望的结果。在此小编也遇到同样的问题,那么mapreduce如何实现计数呢,首先我们看下mapreduce的基本语法:
db.runCommand( { mapreduce : 字符串,集合名, map : 函数,见下文 reduce : 函数,见下文 [, query : 文档,发往map函数前先给过渡文档] [, sort : 文档,发往map函数前先给文档排序] [, limit : 整数,发往map函数的文档数量上限] [, out : 字符串,统计结果保存的集合] [, keeptemp: 布尔值,链接关闭时临时结果集合是否保存] [, finalize : 函数,将reduce的结果送给这个函数,做最后的处理] [, scope : 文档,js代码中要用到的变量] [, jsMode : 布尔值,是否减少执行过程中BSON和JS的转换,默认true] //注:false时 BSON-->JS-->map-->BSON-->JS-->reduce-->BSON,可处理非常大的mapreduce, //true时BSON-->js-->map-->reduce-->BSON [, verbose : 布尔值,是否产生更加详细的服务器日志,默认true] } );
看到number了么,number在map中使用 1 作为它的固定的value
//map示例 $map = 'function(){ var key = { advert_id : this.advert_id, district_code : this.district_code }; var values = { amount: this.amount, number: 1, advertiser_id: this.advertiser_id }; emit(key, values); }';
接下来在reduce中使用 values[i].number;来计数即可
//reduce示例 $reduce = 'function(key, values){ var result = {amount:0, number:0, advertiser_id:0}; for(var i in values) { result.advertiser_id = values[i].advertiser_id; result.amount += values[i].amount; result.number += values[i].number;//注意:数量统计时,不是这里+1即可,需要通过 //values[i].number来赋值 } return result; }'; $query = null;
总结:使用MapReduce时,尽量只用到累加、累减、累乘等基本操作,不要去用++、push、delete等可能会产生风险的操作