Воссоединение сплит-картографических массивов в Монго - PullRequest
2 голосов
/ 12 ноября 2011

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

function () {

    m = function () {
            emit(this.city, {num:1, arr:this});
    }

    r = function (key, arr_values) {
            var resultArray = [];
            var count = 0;
            arr_values.forEach(function (value) {
                                    resultArray.push(value);
                                    count++;
                                });
            return {num:count, arr:resultArray};
    }

    res = db.AdsOnPage.mapReduce(m, r, {out:"ReducedCollection"});


}

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

{
  "city":"Chicago",
  "value" : {
    "num" : 2.0,
    "arr" : [{
        "num" : 2.0,
        "arr" : [{
            "num" : 1.0,
            "arr" : [{
                <user doc is here>
              }]
          }, {
            "num" : 1.0,
            "arr" : [{
                <user doc is here>
              }]
          }]
      }
.......
for many many arrays

Почему это происходит?Есть ли способ объединить мои результаты в единый массив?

Ответы [ 2 ]

1 голос
/ 12 ноября 2011

Ничего общего с шардингом, это связано с логикой Map / Reduce.

value из функции map должна иметь ту же форму, что и возврат из reduce.

Помните, что reduce может быть запущен несколько раз. Фактически, в случае шардинга, он будет запускаться один раз для каждого шарда и затем снова mongos, делающим запрос.

Ты думаешь о том, что происходит, когда ты бежишь

reduce(key, [a,b,c])

Для работы Map / Reduce выходные данные должны совпадать со следующими:

reduce(key, [a, reduce(key, [b,c]) ) ИЛИ

reduce(key, [reduce(key, [a,b]), c] )

В вашем случае reduce(key, [b,c]) возвращает массив, поэтому вы получаете следующее:

reduce(key, [a, reduce(key, [b,c]) ) => reduce(key, [a, [b,c] ])

Заметили дополнительный массив? Вот почему вы получаете вложение.

Для решения этой проблемы необходимо две части.

  1. Если values будет массивом, то emit должен вывести массив с одним элементом в нем.
  2. Когда вы сделаете это изменение, arr_values будет «массивом массивов». Вам придется их правильно комбинировать.

Надеюсь, это указывает на правильное направление. Для более подробных методов отладки вы можете обратиться к странице Устранение неполадок M / R .

0 голосов
/ 18 августа 2015

Я использую функцию массива Array.isArray (param) и indexOf (param) для решения этой проблемы, но я помещаю уникальный элемент в мой массив стека.

if(Array.isArray(param)) {
    for(var i in param) {
       if(stack.indexOf(param[i]) == -1)
           arr.push(param[i]) ;
    }
}
else {
    if(stack.indexOf(param) == -1)
        arr.push(param) ;
}

Вы можете попробовать Array.isArray ().

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