Určitě to zvládneš. Na vaše otázky odpovím jeden po druhém:
1. Spolu s map-reduce můžete zadat dotaz, který filtruje sadu objektů, které budou předány do fáze mapy. V mongo shell by to vypadalo takto (za předpokladu m
a r
jsou názvy funkcí vašeho mapovače a reduktoru):
> db.coll.mapReduce(m, r, {query: {$or: [{"recently-voted": true}, {"hourly-score": {$gt: 0}}]}})
2. Krok č. 1 vám umožní použít váš mapovač na všechny dokumenty s alespoň jedním hlasem za poslední hodinu (nebo s recently-voted
nastaveno na true), ale ne všechny hlasy byly za poslední hodinu. Budete tedy muset filtrovat seznam v mapovači a vydávat pouze ty hlasy, které chcete započítat:
function m() {
var hour_ago = new Date() - 3600000;
this.votes.forEach(function (vote) {
if (vote.ts > hour_ago) {
emit(/* your key */, this.vote.a);
}
});
}
A ke snížení:
function r(key, values) {
var sum = 0;
values.forEach(function(value) { sum += value; });
return sum;
}
3. Chcete-li aktualizovat tabulku hodinových skóre, můžete použít reduceOutput
možnost map-reduce, která zavolá váš reduktor s emitovanými hodnotami a dříve uloženou hodnotou ve výstupní kolekci (pokud existuje). Výsledek tohoto průchodu bude uložen do výstupní kolekce. Vypadá to takto:
> db.coll.mapReduce(m, r, {query: ..., out: {reduce: "output_coll"}})
Kromě opětovného snížení výstupu můžete použít merge
který přepíše dokumenty ve výstupní kolekci nově vytvořenými (ale ponechá za sebou všechny dokumenty s _id
jiný než _id
s vytvořené vaší úlohou m-r), replace
, což je ve skutečnosti operace typu drop-and-create a je výchozí, nebo použijte {inline: 1}
, který vrátí výsledky přímo do shellu nebo do vašeho ovladače. Všimněte si, že při použití {inline: 1}
, vaše výsledky se musí vejít do velikosti povolené pro jeden dokument (16 MB v posledních verzích MongoDB).
(4.)Můžete spouštět úlohy redukce map na sekundárních zařízeních ("slave"), ale protože sekundární nemohou přijímat zápisy (to je dělá sekundární), můžete to udělat pouze při použití inline výstupu.