设为首页 收藏本站
查看: 953|回复: 0

[经验分享] mongodb mapreduce小试

[复制链接]

尚未签到

发表于 2015-7-7 05:50:08 | 显示全部楼层 |阅读模式
  最近由于产品业务的需求,需要使用一些数据量比较相对有点大的计算,顺便试试mongodb的mapreduce功能,感觉还不错
  
  下面是官方提供的一个例子:



$ ./mongo
> db.things.insert( { _id : 1, tags : ['dog', 'cat'] } );
> db.things.insert( { _id : 2, tags : ['cat'] } );
> db.things.insert( { _id : 3, tags : ['mouse', 'cat', 'dog'] } );
> db.things.insert( { _id : 4, tags : []  } );
> // map function
> m = function(){
...    this.tags.forEach(
...        function(z){
...            emit( z , { count : 1 } );
...        }
...    );
...};
> // reduce function
> r = function( key , values ){
...    var total = 0;
...    for ( var i=0; i res = db.things.mapReduce(m,r);
> res
{"timeMillis.emit" : 9 , "result" : "mr.things.1254430454.3" ,
"numObjects" : 4 , "timeMillis" : 9 , "errmsg" : "" , "ok" : 0}
> db[res.result].find()
{"_id" : "cat" , "value" : {"count" : 3}}
{"_id" : "dog" , "value" : {"count" : 2}}
{"_id" : "mouse" , "value" : {"count" : 1}}
> db[res.result].drop()
  mapreduce参数说明



db.runCommand(
{
mapreduce : ,  
map : ,   
reduce :   
[, query : ]   
[, sort : ]   
[, limit : ]   
[, out : ]   
[, keeptemp: ]   
[, finalize : ]   
[, scope : ]   
[, verbose : true]  
});
  mapreduce:指定要进行mapreduce处理的collection
    map:map函数
    reduce:reduce函数
    query:一个筛选条件,只有满足条件的行才会加入mapreduce集合,而这个筛选过程是先于整个mapreduce流程而执行的
    sort:和query结合的sort排序参数,这是唯一可以优化分组机制的地方
    limit:同上
    out:结果输出的collection的名字,不指定会默认创建一个随机名字的collection
    keytemp:true或false,表明结果输出到的collection是否是临时的,如果为true,则会在客户端连接中断后自动删除,如果你用的是MongoDB的mongo客户端连接,那必须exit后才会删除。如果是脚本执行,脚本退出或调用close会自动删除结果collection
    finalize:和map,reduce一样是一个函数,它可以在reduce得出一个结果后再对key和value进行一次计算并返回一个最终结果
    scope:设置参数值,在这里设置的值在map,reduce,finalize函数中可见
    verbose:在执行过程中打印调试信息。
  返回格式:



{
result : ,   
counts : {input :  , emit  : , output : } ,
timeMillis : ,
ok : ,
[, err : ]
}
  
   下面来一个略微复杂一点的例子,下面是统计房源列表页房源的曝光量:
  mongodb数据格式:



{ "_id" : ObjectId("50364d9fdec7d5ce4000198d"), "pn" : "Listing_V2_IndexPage_All", "guid" : "E200F425-30E7-0D97-9B3A-E047A08CE47C", "uguid" : "4455754C-B2A0-7EDA-6387-A50F0228DE7F", "url" : "http://shanghai.haozu.com/listing/pudong/?from=in_area", "referer" : "http://shanghai.haozu.com/", "site" : "haozu", "stamp" : "1345691212948", "cip" : "116.231.123.184", "sessid" : "B1197AA0-976C-F6EF-BB6F-9401D8E983DD", "cid" : "11", "cstamp" : "1345691178421", "cstparam" : "{\"found\":\"37695\",\"proids\":\"10290023|10353348|8448223|10310737|10311720|10250125|10320886|8507299|10332158|10341287|10266002|10322302|9185878|10273552|10272872|10282252|10270250|10336122|9350169|10196350|8533446|10250019|10335617|10222489\"}", "rfpn" : "Home_Index8Page", "agent" : "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; 360SE; 360SE)" }
  房源id保存在cstparam字段里面,是一个字符串,因此需要正则进行一下匹配,然后取出进行统计
,因此对应的map,reduce的写法为:
  map方法:



var m=function () {
var arr = this.cstparam.split("\"");
var str_ids = arr[arr.length - 2];
var arr_ids = str_ids.split("|");
for (var i in arr_ids) {
emit(arr_ids, 1);
}
}
  reduce方法:



var reduce=function (key, emits) {
var count = 0;
for (var i in emits) {
count += emits;
}
return count;
}
  执行:



db.log_soj.mapReduce(map,reduce,{out:'result_tmp',query:{'cstparam':{'$exists':true},'cstparam':/proids/}});
  返回结果:



{
"result" : "result_tmp",
"timeMillis" : 18888,
"counts" : {
"input" : 15742,
"emit" : 333011,
"reduce" : 103137,
"output" : 150897
},
"ok" : 1,
}
  结果集:



{ "_id" : "10000003", "value" : 1 }
{ "_id" : "10000016", "value" : 2 }
{ "_id" : "10000032", "value" : 1 }
{ "_id" : "10000039", "value" : 1 }
{ "_id" : "10000043", "value" : 1 }
{ "_id" : "10000059", "value" : 1 }
  
  再来一个,和上例类似,但是按照房源所出现的城市进行曝光量的统计
  map函数:



function () {
var arr = this.cstparam.split("\"");
var str_ids = arr[arr.length - 2];
var arr_ids = str_ids.split("|");
for (var i in arr_ids) {
var key = arr_ids + "_" + this.cid;
emit(key, {prop_id:arr_ids, city_id:this.cid, count:1});
}
}
  reduce函数:



function (key, emits) {
var total = 0;
for (var i in emits) {
total += emits.count;
}
return {prop_id:emits[0].prop_id, city_id:emits[0].city_id, count:total};
}
  执行:



db.log_soj.mapReduce(m1,r1,{out:'result_tmp',query:{'cstparam':{'$exists':true},'cstparam':/proids/}});
  结果:



{ "_id" : "10000003_undefined", "value" : { "prop_id" : "10000003", "city_id" : null, "count" : 1 } }
{ "_id" : "10000016_14", "value" : { "prop_id" : "10000016", "city_id" : "14", "count" : 2 } }
{ "_id" : "10000032_15", "value" : { "prop_id" : "10000032", "city_id" : "15", "count" : 1 } }
{ "_id" : "10000039_15", "value" : { "prop_id" : "10000039", "city_id" : "15", "count" : 1 } }
{ "_id" : "10000043_11", "value" : { "prop_id" : "10000043", "city_id" : "11", "count" : 1 } }
{ "_id" : "10000059_17", "value" : { "prop_id" : "10000059", "city_id" : "17", "count" : 1 } }
{ "_id" : "10000068_11", "value" : { "prop_id" : "10000068", "city_id" : "11", "count" : 1 } }
{ "_id" : "10000099_15", "value" : { "prop_id" : "10000099", "city_id" : "15", "count" : 1 } }
{ "_id" : "10000100_18", "value" : { "prop_id" : "10000100", "city_id" : "18", "count" : 1 } }
{ "_id" : "10000106_14", "value" : { "prop_id" : "10000106", "city_id" : "14", "count" : 1 } }
{ "_id" : "10000109_18", "value" : { "prop_id" : "10000109", "city_id" : "18", "count" : 3 } }
{ "_id" : "10000112_15", "value" : { "prop_id" : "10000112", "city_id" : "15", "count" : 1 } }
{ "_id" : "10000118_15", "value" : { "prop_id" : "10000118", "city_id" : "15", "count" : 1 } }
{ "_id" : "10000156_11", "value" : { "prop_id" : "10000156", "city_id" : "11", "count" : 1 } }
{ "_id" : "10000224_14", "value" : { "prop_id" : "10000224", "city_id" : "14", "count" : 1 } }
{ "_id" : "10000250_22", "value" : { "prop_id" : "10000250", "city_id" : "22", "count" : 1 } }
{ "_id" : "10000262_25", "value" : { "prop_id" : "10000262", "city_id" : "25", "count" : 1 } }
{ "_id" : "10000267_14", "value" : { "prop_id" : "10000267", "city_id" : "14", "count" : 3 } }
{ "_id" : "10000305_14", "value" : { "prop_id" : "10000305", "city_id" : "14", "count" : 3 } }
{ "_id" : "10000323_11", "value" : { "prop_id" : "10000323", "city_id" : "11", "count" : 1 } }
  转载请注明出处:
  http://www.iyunv.com/xiazh/archive/2012/09/05/2671730.html

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-83833-1-1.html 上篇帖子: 大数据存储:MongoDB实战指南——常见问题解答 下篇帖子: [mongodb]使用mongodb中数组元素的下标来做更新(update)多维数组
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表