Funkcję zmniejszania można wywołać raz, z kluczem i wszystkimi odpowiadającymi im wartościami (ale tylko wtedy, gdy klucz ma wiele wartości - nie zostanie wywołany w ogóle, jeśli klucz ma tylko jedną wartość).
Może być również wywoływany wielokrotnie, za każdym razem z kluczem i tylko podzbiorem odpowiednich wartości i poprzednie wyniki redukcji dla tego klucza. Ten scenariusz nazywa się ponowną redukcją . Aby wesprzeć ponowne redukcje, twoja funkcja redukcji powinna być idempotentna.
Istnieją dwie kluczowe funkcje w idempotentnej funkcji redukcji:
- Wartość zwrotu funkcji Reduce powinna być w tym samym formacie co wartości to przyjmuje. Tak więc, jeśli twoja funkcja zmniejszania akceptuje tablicę ciągów, funkcja powinna zwrócić ciąg. Jeśli akceptuje obiekty z kilkoma właściwościami, powinien zwrócić obiekt zawierający te same właściwości. Gwarantuje to, że funkcja nie zostanie przerwana, gdy zostanie wywołana z wynikiem poprzedniej redukcji.
- Nie rób założeń na podstawie liczby wartości przyjmuje. Nie ma gwarancji, że
values
parametr zawiera wszystkie wartości dla danego klucza. Używającvalues.length
w obliczeniach jest bardzo ryzykowna i należy jej unikać.
Aktualizacja: Poniższe dwa kroki nie są wymagane (a nawet możliwe, nie sprawdziłem) w nowszych wydaniach MongoDB. Może teraz wykonać te kroki za Ciebie, jeśli określisz kolekcję wyników w opcjach map-reduce:
{ out: { reduce: "tempResult" } }
Jeśli twoja funkcja zmniejszania jest idempotentna, nie powinieneś mieć żadnych problemów z redukcją wielu kolekcji. Po prostu ponownie zmniejsz wyniki każdej kolekcji:
Krok 1
Uruchom redukcję mapy na każdym wymaganym zbiorze i zapisz wyniki w jednym, tymczasowym zbiorze. Możesz zapisać wyniki za pomocą funkcji finalizacji:
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 })
Krok 2
Uruchom kolejną redukcję mapy w kolekcji tymczasowej, używając tej samej funkcji zmniejszania . Funkcja map to prosta funkcja, która wybiera klucze i wartości z tymczasowej kolekcji:
map = function () {
emit(this._id, this.value);
}
db.tempResult.mapReduce(map, reduce)
Ta druga redukcja mapy jest w zasadzie ponowną redukcją i powinna dać ci potrzebne wyniki.