Zdecydowanie możesz to zrobić. Zajmę się Twoimi pytaniami pojedynczo:
1. Możesz określić zapytanie wraz z map-reduce, które filtruje zbiór obiektów, które zostaną przekazane do fazy mapy. W powłoce mongo wyglądałoby to tak (zakładając, że m
i r
to odpowiednio nazwy funkcji mapowania i reduktora):
> db.coll.mapReduce(m, r, {query: {$or: [{"recently-voted": true}, {"hourly-score": {$gt: 0}}]}})
2.Krok #1 pozwoli ci użyć twojego mapera na wszystkich dokumentach z co najmniej jednym głosem w ciągu ostatniej godziny (lub z recently-voted
ustawione na true), ale nie wszystkie głosy zostaną oddane w ciągu ostatniej godziny. Musisz więc filtrować listę w swoim programie do tworzenia map i emitować tylko te głosy, które chcesz policzyć:
function m() {
var hour_ago = new Date() - 3600000;
this.votes.forEach(function (vote) {
if (vote.ts > hour_ago) {
emit(/* your key */, this.vote.a);
}
});
}
I do zmniejszenia:
function r(key, values) {
var sum = 0;
values.forEach(function(value) { sum += value; });
return sum;
}
3. Aby zaktualizować tabelę wyników godzinowych, możesz użyć reduceOutput
opcja map-reduce, która wywoła twój reduktor zarówno z emitowanymi wartościami, jak i wcześniej zapisaną wartością w kolekcji wyjściowej (jeśli istnieje). Wynik tego przebiegu zostanie zapisany w kolekcji danych wyjściowych. Wygląda to tak:
> db.coll.mapReduce(m, r, {query: ..., out: {reduce: "output_coll"}})
Oprócz ponownego zmniejszenia danych wyjściowych, możesz użyć merge
który nadpisze dokumenty w kolekcji wyjściowej nowo utworzonymi (ale pozostawi wszelkie dokumenty z _id
inny niż _id
s utworzone przez Twoje zadanie m-r), replace
, która w rzeczywistości jest operacją upuść i utwórz i jest domyślna, lub użyj {inline: 1}
, który zwróci wyniki bezpośrednio do powłoki lub do sterownika. Pamiętaj, że używając {inline: 1}
, Twoje wyniki muszą mieścić się w rozmiarze dozwolonym dla pojedynczego dokumentu (16 MB w ostatnich wydaniach MongoDB).
(4.)Możesz uruchamiać zadania redukujące mapę na wtórnych ("slave"), ale ponieważ drugorzędne nie mogą akceptować zapisów (dlatego są drugorzędne), możesz to zrobić tylko podczas korzystania z wbudowanego wyjścia.