Как рассчитать количество и уникальный счет по двум полям в функции Монго уменьшить - PullRequest
3 голосов
/ 31 января 2012

У меня есть таблица отслеживания ссылок, которая имеет (среди прочих полей) track_redirect и track_userid. Я хотел бы вывести как общее количество для данной ссылки, а также уникальный счетчик - подсчет дубликатов по идентификатору пользователя. Таким образом, мы можем различить, если кто-то щелкнул по той же ссылке 5 раз.

Я пытался создать this.track_userid как в части ключа, так и в части значений, но не могу понять, как правильно получить к ним доступ в функции сокращения.

Так что, если я вернусь к тому, когда он действительно заработал, у меня будет очень простой код ниже - точно так же, как это было бы в примере с «моей первой функцией редуцирования»

карта

function() {
  if(this.track_redirect) {
    emit(this.track_redirect,1); 
  }
}

1010 * снизить *

function(k, vals) {
  var sum = 0;
  for (var i in vals) {
    sum += vals[i];
  } 
  return sum;
}

Я хотел бы знать, как правильно вывести дополнительную информацию об идентификаторе пользователя и получить к ней доступ в карте, пожалуйста. или я думаю об этом не так?

в случае, если неясно, я не хочу подсчитывать общее количество кликов, сделанных идентификатором пользователя, но подсчитывать уникальные клики каждого URL-адреса и идентификатора пользователя - не считая повторных кликов, совершенных идентификатором пользователя по каждой ссылке

Может кто-нибудь указать мне правильное направление, пожалуйста? спасибо!

1 Ответ

4 голосов
/ 01 февраля 2012

Вы можете фактически передать произвольный объект по второму параметру вызова 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:
  // /20828/kak-naiti-klychi-hesha
  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 }});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...