Ответ 1
Функция уменьшения объединяет документы с одним и тем же ключом в один документ. Если функция карты испускает один документ для определенного ключа (как в случае с ключом 3), функция уменьшения не будет вызываться.
Итак, я новичок в 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? Для пимонго (который я использую)?
Функция уменьшения объединяет документы с одним и тем же ключом в один документ. Если функция карты испускает один документ для определенного ключа (как в случае с ключом 3), функция уменьшения не будет вызываться.
Я понимаю, что это более старый вопрос, но я пришел к нему и почувствовал, что до сих пор не понял, почему такое поведение существует и как создавать функции map/reduce, поэтому это не проблема.
Причина, по которой MongoDB не вызывает функцию уменьшения, если есть один экземпляр ключа, потому что он не нужен (я надеюсь, что это будет иметь больше смысла в данный момент). Ниже приведены требования для сокращения функций:
- Функция уменьшения должна возвращать объект, тип которого должен быть идентичен для типа значения, испускаемого функцией карты.
- Порядок элементов в значенияхArray не должен влиять на вывод функции уменьшения
- Функция уменьшения должна быть идемпотентной.
Первое требование очень важно, и кажется, что многие люди его не замечают, потому что я видел, как много людей отображают функцию сокращения, а затем обрабатывают одно ключевой случай в функции finalize. Это неправильный способ решения проблемы.
Подумайте об этом так: если есть только один экземпляр ключа, простая оптимизация - полностью пропустить редуктор (там нечего уменьшать). Однозначные значения по-прежнему включаются в выход, но цель редуктора заключается в создании совокупного результата многокнопочных документов в вашей коллекции. Если преобразователь и редуктор выводят один и тот же тип, вы должны быть блаженно не осведомлены, посмотрев на структуру объекта вывода из ваших функций map/reduce. Вам не нужно использовать функцию финализации для исправления структуры объектов, которые не выполнялись через редуктор.
Короче говоря, сделайте свое сопоставление в своей функции карты и уменьшите значения нескольких ключей в единый совокупный результат в ваших уменьшающих функциях.
Решение:
в завершить выполнить проверку этого поля и выполнить необходимые действия
$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;
};");
"MongoDB не будет вызывать функцию сокращения для ключа, который имеет только одно значение. Аргумент значений - это массив, элементами которого являются объекты значений, которые" отображаются "на ключ."
http://docs.mongodb.org/manual/reference/command/mapReduce/#mapreduce-reduce-cmd
Является ли это естественное поведение mapreduce вообще?
Да.