mongodb mapreduce - построить массив или объект в редукторе? - PullRequest
2 голосов
/ 05 января 2011

оригинальная коллекция:

{ 
"_id" : ObjectId('xxxxxxxxxxxxxxxx'),
  "userId" : ObjectId('yyyyyyyyyyyyyyyy'),
  "urlId" : ObjectId('zzzzzzzzzzzzzzzzzz')
},
{ 
  "_id" : ObjectId('uuuuuuuuuuuuuuuuuu'),
  "userId" : ObjectId('aaaaaaaaaaaaaaaa'),
  "urlId" : ObjectId('zzzzzzzzzzzzzzzzzz')
}

выделяют:

emit(this.urlId, {userId: this.userId, visitCount: this.visitCount});

уменьшить:

function(key, values) {
    var visitCount = 0;
    var userVC = new Array();
    values.forEach(function(doc) {


NOT SURE WHAT TO PUT HERE TO ACHIEVE DESIRED OUTPUT COLLECTION


    });
    return {urlId: key, userVC: userVC};
};

желаемый набор выходных данных MR:

{
   "_id" : ObjectId('zzzzzzzzzzzzzzzzzzzz'),
   "value" : {
       "urlId" : ObjectId('zzzzzzzzzzzzzzzzzzzz'),
       "userVC" : {
              ObjectId('yyyyyyyyyyyyyyyy') : <total visit count for this userId on this urlId>,
              ObjectId('aaaaaaaaaaaaaaaa') : <total visit count for this userId on this urlId>
       }
}

Ответы [ 2 ]

4 голосов
/ 05 января 2011

Вы хотите знать, сколько раз каждый пользователь посещал каждый отдельный URL на вашем сайте? Я думаю, вы захотите решить это по-другому.

Излучить количество посещений URL / пользователей:

emit( { urlId: this.urlId, userId: this.userId }, { count: 1 } );

Подсчитайте их с помощью уменьшения:

r = function( key , values ){
    var total = 0;
    for ( var i=0; i<values.length; i++ )
        total += values[i].count;
    return { count : total };
};

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

Вот ссылка, которая не совсем соответствует вашей заявленной цели, но я нашел очень полезным, пытаясь понять, как работают эти функции mongodb mapreduce:

http://cookbook.mongodb.org/patterns/unique_items_map_reduce/

0 голосов
/ 12 октября 2016

Для всех, кто пытается решить эту проблему с помощью функции сокращения:

function reduce(key, values) {
  const result = {
    list: [],
    ...
  };

  // keep track of reduced records to avoid duplicate list entries
  const processed = {
    list: [],
    ...
  };

  values.forEach((value, index) => {
    if (value.listItem && value.listItem.length > 0) {

      // our value is an array as MongoDB needs to be strongly typed (same as reduced type)
      if (processed.list.indexOf(value.listItem[0].key) === -1) {
        result.list = result.list.concat(value.listItem);
      }

    }
    ...
  });

  return result;
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...