Подтвердить что ты не робот

MongoDB MapReduce - введите один ключ/одно значение не вызывает сокращение

Итак, я новичок в mongodb и mapreduce вообще и наткнулся на эту "причуду" (или, по крайней мере, на мой взгляд, причуду)

Скажем, что у меня есть объекты в моей коллекции:

{'key': 5, 'value': 5}

{'key': 5, 'value': 4}

{'key': 5, 'value': 1}

{'key': 4, 'value': 6}

{'key': 4, 'value': 4}

{'key': 3, 'value': 0}

Моя функция map просто испускает ключ и значение

Функция уменьшает, просто добавляет значения И, прежде чем возвращать их добавляет 1 (я сделал это, чтобы проверить, не вызвана ли функция сокращения)

Мои результаты:

{'_ id': 3, 'значение': 0}

{'_ id': 4, 'value': 11.0}

{'_ id': 5, 'value': 11.0}

Как вы можете видеть, для клавиш 4 и 5 я получаю ожидаемый ответ 11 НО для ключа 3 (только с одной записью в коллекции с этим ключом), я получаю неожиданный 0!

Является ли это естественным поведением mapreduce вообще? Для MongoDB? Для пимонго (который я использую)?

4b9b3361

Ответ 1

Функция уменьшения объединяет документы с одним и тем же ключом в один документ. Если функция карты испускает один документ для определенного ключа (как в случае с ключом 3), функция уменьшения не будет вызываться.

Ответ 2

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

Причина, по которой MongoDB не вызывает функцию уменьшения, если есть один экземпляр ключа, потому что он не нужен (я надеюсь, что это будет иметь больше смысла в данный момент). Ниже приведены требования для сокращения функций:

  • Функция уменьшения должна возвращать объект, тип которого должен быть идентичен для типа значения, испускаемого функцией карты.
  • Порядок элементов в значенияхArray не должен влиять на вывод функции уменьшения
  • Функция уменьшения должна быть идемпотентной.

Первое требование очень важно, и кажется, что многие люди его не замечают, потому что я видел, как много людей отображают функцию сокращения, а затем обрабатывают одно ключевой случай в функции finalize. Это неправильный способ решения проблемы.

Подумайте об этом так: если есть только один экземпляр ключа, простая оптимизация - полностью пропустить редуктор (там нечего уменьшать). Однозначные значения по-прежнему включаются в выход, но цель редуктора заключается в создании совокупного результата многокнопочных документов в вашей коллекции. Если преобразователь и редуктор выводят один и тот же тип, вы должны быть блаженно не осведомлены, посмотрев на структуру объекта вывода из ваших функций map/reduce. Вам не нужно использовать функцию финализации для исправления структуры объектов, которые не выполнялись через редуктор.

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

Ответ 3

Решение:

  • добавлено новое поле в карте: single: 0
  • в уменьшить измените это поле на: single: 1
  • в завершить выполнить проверку этого поля и выполнить необходимые действия

    $map = new MongoCode("function() {
        var value = {
            time: this.time,
            email_id: this.email_id,
            single: 0
        };
    
        emit(this.email, value);
    }");
    
    $reduce = new MongoCode("function(k, vals) {
    
        // make some need actions here
        return {
            time: vals[0].time,
            email_id: vals[0].email_id,
            single: 1
        };
    }");
    
    $finalize = new MongoCode("function(key, reducedVal) {
        if (reducedVal.single == 0) {
            reducedVal.time = 11111;
        }
        return reducedVal;
    };");
    

Ответ 4

"MongoDB не будет вызывать функцию сокращения для ключа, который имеет только одно значение. Аргумент значений - это массив, элементами которого являются объекты значений, которые" отображаются "на ключ."

http://docs.mongodb.org/manual/reference/command/mapReduce/#mapreduce-reduce-cmd

Ответ 5

Является ли это естественное поведение mapreduce вообще?

Да.