Функция за намаляване може да бъде извикана веднъж, с ключ и всички съответни стойности (но само ако има няколко стойности за ключа - той изобщо няма да бъде извикан, ако има само 1 стойност за ключа).
Може също да се извиква няколко пъти, всеки път с ключ и само подмножество от съответните стойности , а предишните намаляват резултатите за този ключ. Този сценарий се нарича повторно намаляване . За да поддържате re-reduces, вашата функция за намаляване трябва да бъде идемпотентна.
Има две ключови характеристики в идемпотентната функция за намаляване:
- Връщаната стойност на функцията за намаляване трябва да е в същия формат като стойностите Така че, ако вашата функция за намаляване приема масив от низове, функцията трябва да върне низ. Ако приема обекти с няколко свойства, трябва да върне обект, съдържащ същите тези свойства. Това гарантира, че функцията няма да се счупи, когато бъде извикана с резултат от предишно намаляване.
- Не правете предположения въз основа на броя на стойностите той приема. Не е гарантирано, че
values
параметърът съдържа всички стойностите за дадения ключ. Така че използвайкиvalues.length
в изчисленията е много рисковано и трябва да се избягва.
Актуализация: Двете стъпки по-долу не са задължителни (или дори са възможни, не съм проверил) за по-новите версии на MongoDB. Вече може да се справи с тези стъпки вместо вас, ако посочите изходна колекция в опциите за намаляване на картата:
{ out: { reduce: "tempResult" } }
Ако функцията ви за намаляване е идемпотентна, не би трябвало да имате проблеми с намаляването на картата на множество колекции. Просто намалете отново резултатите от всяка колекция:
Стъпка 1
Изпълнете map-reduce за всяка необходима колекция и запишете резултатите в единична временна колекция. Можете да съхранявате резултатите с помощта на функция за финализиране:
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-reduce на временната колекция, използвайки същата функция за намаляване . Функцията map е проста функция, която избира ключовете и стойностите от временната колекция:
map = function () {
emit(this._id, this.value);
}
db.tempResult.mapReduce(map, reduce)
Това второ намаляване на картата е основно повторно намаляване и трябва да ви даде нужните резултати.