我有一个链接跟踪表,其中包含track_redirect和track_userid(以及其他字段)。我想输出给定链接的总计数,以及唯一计数 - 按用户ID计算重复数。因此,如果有人点击了同一个链接5次,我们可以区分。
我已尝试在键和值部分中发出this.track_userid,但无法掌握如何在reduce函数中正确访问它们。
因此,如果我回滚到它实际工作的时候,我会在下面提供非常简单的代码 - 就像它在'我的第一个mapreduce函数'示例中一样
地图
function() {
if(this.track_redirect) {
emit(this.track_redirect,1);
}
}
减少
function(k, vals) {
var sum = 0;
for (var i in vals) {
sum += vals[i];
}
return sum;
}
我想知道发出额外的用户ID信息并在mapreduce中访问它的正确方法。或者我是以错误的方式思考它?
如果不清楚,我不想计算用户ID所做的总点击次数,而是计算每个网址+用户ID的唯一点击次数 - 不计算用户ID在每个链接上的任何重复点击次数
有人能指出我正确的方向吗?谢谢!
答案 0 :(得分:4)
您实际上可以在emit调用的第二个参数上传递任意对象。这意味着您可以利用此功能并将用户标识存储在其中。例如,您的地图功能可能如下所示:
var mapFunc = function() {
if (this.track_redirect) {
var tempDoc = {};
tempDoc[this.track_userid] = 1;
emit(this.track_redirect, {
users_clicked: tempDoc,
total_clicks: 1
});
}
};
你的reduce函数可能如下所示:
var reduceFunc = function(key, values) {
var summary = {
users_clicked: {},
total_clicks: 0
};
values.forEach(function (doc) {
summary.total_clicks += doc.total_clicks;
// Merge the properties of 2 objects together
// (and these are actually the userids)
Object.extend(summary.users_clicked, doc.users_clicked);
});
return summary;
};
摘要对象的users_clicked属性基本上将每个用户的id存储为属性(因为您不能拥有重复的属性,您可以保证它将存储唯一的用户)。另请注意,您必须注意以下事实:传递给reduce函数的某些值可能是先前reduce的结果,并且上面的示例代码将此考虑在内。您可以在文档here中找到有关所述行为的更多信息。
为了获得唯一计数,您可以传递在reduce阶段完成时调用的终结函数:
var finalFunc = function(key, value) {
// Counts the keys of an object. Taken from:
// http://stackoverflow.com/questions/18912/how-to-find-keys-of-a-hash
var countKeys = function(obj) {
var count = 0;
for(var i in obj) {
if (obj.hasOwnProperty(i))
{
count++;
}
}
return count;
};
return {
redirect: key,
total_clicks: value.total_clicks,
unique_clicks: countKeys(value.users_clicked)
};
};
最后,您可以像这样执行map reduce作业(修改out属性以满足您的需要):
db.users.mapReduce(mapFunc, reduceFunc, { finalize: finalFunc, out: { inline: 1 }});