Ответ 1
Функция сокращения может вызываться один раз с ключом и всеми соответствующими значениями (но только если для ключа есть несколько значений - он вообще не будет вызываться, если только 1 значение для ключа).
Он также может быть вызван несколько раз, каждый раз с ключом и только подмножество соответствующих значений, а предыдущие уменьшают результаты для этого ключа. Этот сценарий называется re-reduce. Для поддержки повторного уменьшения ваша функция сокращения должна быть idempotent.
В функции уменьшения идемпотента есть две ключевые функции:
- возвращаемое значение функции уменьшения должно быть в в том же формате, что и значения. Таким образом, если функция сокращения принимает массив строк, функция должна возвращать строку. Если он принимает объекты с несколькими свойствами, он должен вернуть объект, содержащий те же свойства. Это гарантирует, что функция не сломается, когда она вызывается с результатом предыдущего уменьшения.
- Не делайте предположений на основе количества значений, которое требуется. Не гарантируется, что параметр
values
содержит все значения для данного ключа. Поэтому использованиеvalues.length
в расчетах является очень рискованным и его следует избегать.
Обновление: Два нижеследующих шага не требуются (или даже возможно, я не проверял) в более поздних выпусках MongoDB. Теперь он может обрабатывать эти действия для вас, если вы укажете выходную коллекцию в map-reduce options:
{ out: { reduce: "tempResult" } }
Если ваша функция сокращения идемпотентна, у вас не должно возникнуть проблем с отображением нескольких коллекций. Просто заново уменьшите результаты каждой коллекции:
Шаг 1
Запустите сокращение карты для каждой требуемой коллекции и сохраните результаты в одной временной коллекции. Вы можете сохранить результаты, используя завершить функцию:
finalize = function (key, value) {
db.tempResult.save({ _id: key, value: value });
}
db.someCollection.mapReduce(map, reduce, { finalize: finalize })
db.anotherCollection.mapReduce(map, reduce, { finalize: finalize })
Шаг 2
Запустите еще один снимок карты во временной коллекции , используя ту же функцию сокращения. Функция map - это простая функция, которая выбирает ключи и значения из временной коллекции:
map = function () {
emit(this._id, this.value);
}
db.tempResult.mapReduce(map, reduce)
Этот второй снимок карты в основном редуцирует и должен дать вам нужные результаты.