Você definitivamente pode fazer isso. Vou responder suas perguntas uma de cada vez:
1.Você pode especificar uma consulta junto com seu map-reduce, que filtra o conjunto de objetos que serão passados para a fase de mapa. No shell do mongo, isso se pareceria (assumindo que
m
e r
são os nomes de suas funções mapeadora e redutora, respectivamente):> db.coll.mapReduce(m, r, {query: {$or: [{"recently-voted": true}, {"hourly-score": {$gt: 0}}]}})
2.A etapa 1 permitirá que você use seu mapeador em todos os documentos com pelo menos um voto na última hora (ou com
recently-voted
definido como verdadeiro), mas nem todos os votos foram na última hora. Portanto, você precisará filtrar a lista no seu mapeador e emitir apenas os votos que deseja contar:function m() {
var hour_ago = new Date() - 3600000;
this.votes.forEach(function (vote) {
if (vote.ts > hour_ago) {
emit(/* your key */, this.vote.a);
}
});
}
E para reduzir:
function r(key, values) {
var sum = 0;
values.forEach(function(value) { sum += value; });
return sum;
}
3. Para atualizar a tabela de pontuação horária, você pode usar o
reduceOutput
opção para map-reduce, que chamará seu redutor com os valores emitidos e o valor salvo anteriormente na coleção de saída (se houver). O resultado dessa passagem será salvo na coleção de saída. Isso se parece com:> db.coll.mapReduce(m, r, {query: ..., out: {reduce: "output_coll"}})
Além de reduzir novamente a saída, você pode usar
merge
que irá substituir os documentos na coleção de saída com os recém-criados (mas deixando para trás quaisquer documentos com um _id
diferente do _id
s criados pelo seu trabalho m-r), replace
, que é efetivamente uma operação de soltar e criar e é o padrão, ou use {inline: 1}
, que retornará os resultados diretamente ao shell ou ao seu driver. Observe que ao usar {inline: 1}
, seus resultados devem caber no tamanho permitido para um único documento (16 MB nas versões recentes do MongoDB). (4.) Você pode executar tarefas de redução de mapa em secundários ("escravos"), mas como os secundários não podem aceitar gravações (é isso que os torna secundários), você só pode fazer isso ao usar a saída em linha.