我们有一个看似简单的Map/Reduce任务,每天要处理日志数据。在开发服务器上,我们可以运行这个任务处理大量文档,约1M个文档,一分钟内轻松完成。但是在Amazon EC2生产服务器上,任务将会快速处理约50%的行,然后在其余的数据中爬行。处理几十万个文档可能需要数小时,而不是预期的一两分钟。因此,我希望我们在Map/Reduce任务中没有犯明显的错误。
下面是样本输入文档:
以下是map代码:
下面是样本输入文档:
{ "_id" : ObjectId("4f147a92d72b292c02000057"), "cid" : 25, "ip" : "123.45.67.89", "b" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.63 Safari/535.7", "r" : "", "l" : "en-US,en;q=0.8", "ts" : ISODate("2012-01-16T19:29:22Z"), "s" : 0, "cv" : "4f143a5fd72b292d7f000007", "c" : "" }我们仅查询一系列_id范围。
以下是map代码:
function() { var browser = {} ,referrer = {}; browser[this.b] = { 'count': 1 }; referrer[this.r] = { 'count': 1 }; var objEmit = { 'count': 1 ,'browsers' : browser ,'referrers' : referrer }; var date = this._id.getTimestamp(); date.setHours(0); date.setMinutes(0); date.setSeconds(0); emit({'cv' : this.cv, 'date' : date, 'cid' : this.cid }, objEmit); };以下是reduce代码:
function (key, emits) { var total = 0 ,browsers = {} ,referrers = {}; for (var i in emits) { total += emits[i].count; for (var key in emits[i].browsers) { if (emits[i].browsers.hasOwnProperty(key)) { !(browsers[key]) && (browsers[key] = { count : 0 }); browsers[key].count += emits[i].browsers[key].count; } } for (var key in emits[i].referrers) { if (emits[i].referrers.hasOwnProperty(key)) { !(referrers[key]) && (referrers[key] = { count : 0 }); referrers[key].count += emits[i].referrers[key].count; } } } return {'count' : total, 'browsers' : browsers, 'referrers' : referrers} };
这段代码是一个处理emit数据的函数,主要是计算总数以及浏览器和来源(referrer)的数量。其中,“!”表示not运算符,“&&”表示逻辑与运算符。
在输出map/reduce任务到现有集合时,不需要使用finalize函数,可以将“merge”选项设置为true。希望以上内容对您有所帮助。