Как рассчитать количество и уникальный счет по двум полям в функции Монго уменьшить
У меня есть таблица отслеживания ссылок, которая имеет (среди других полей) track_redirect и track_userid. Я хотел бы вывести как общее количество для данной ссылки, а также уникальный счетчик - подсчет дубликатов по идентификатору пользователя. Таким образом, мы можем различить, если кто-то щелкнул по той же ссылке 5 раз.
Я попытался создать this.track_userid как в части ключа, так и в части значений, но не могу понять, как правильно получить к ним доступ в функции сокращения.
Так что, если я вернусь к тому, когда это действительно сработало, у меня будет очень простой код ниже - точно так же, как это было бы в примере "моя первая функция 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;
}
Я хотел бы знать, как правильно вывести дополнительную информацию об идентификаторе пользователя и получить к ней доступ к карте, пожалуйста. или я думаю об этом не так?
в случае, если неясно, я не хочу подсчитывать общее количество кликов, сделанных идентификатором пользователя, но подсчитывать количество уникальных кликов каждого URL-адреса и идентификатора пользователя - не считая повторных кликов идентификатора пользователя, совершенного в каждой ссылке
Может кто-нибудь указать мне правильное направление, пожалуйста? Спасибо!
1 ответ
Вы можете фактически передать произвольный объект по второму параметру вызова 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
});
}
};
И ваша функция приведения может выглядеть так:
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 объекта итоговой информации в основном сохраняет идентификатор каждого пользователя как свойство (поскольку вы не можете иметь повторяющиеся свойства, вы можете гарантировать, что в нем будут храниться уникальные пользователи). Также обратите внимание, что вы должны быть осторожны с тем фактом, что некоторые значения, передаваемые в функцию сокращения, могут быть результатом предыдущего сокращения, и приведенный выше пример кода учитывает это. Вы можете найти больше информации о поведении в документации здесь.
Чтобы получить уникальный счетчик, вы можете передать функцию финализатора, которая вызывается после завершения фазы сокращения:
var finalFunc = function(key, value) {
// Counts the keys of an object. Taken from:
// http://stackru.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)
};
};
Наконец, вы можете выполнить задание сокращения карты следующим образом (измените атрибут out в соответствии со своими потребностями):
db.users.mapReduce(mapFunc, reduceFunc, { finalize: finalFunc, out: { inline: 1 }});