MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Mapear/reduzir o MongoDB em várias coleções?


Uma função de redução pode ser chamada uma vez, com uma chave e todos os valores correspondentes (mas somente se houver vários valores para a chave - ela não será chamada se houver apenas 1 valor para a chave).

Também pode ser chamado várias vezes, cada vez com uma chave e apenas um subconjunto dos valores correspondentes , e os resultados de redução anteriores para essa chave. Esse cenário é chamado de re-redução . Para suportar re-reduces, sua função de redução deve ser idempotente.

Existem dois recursos principais em uma função de redução idempotente:
  • O valor de retorno da função de redução deve estar no mesmo formato dos valores ela aceita. Então, se sua função reduce aceitar um array de strings, a função deve retornar uma string. Se aceitar objetos com várias propriedades, deve retornar um objeto contendo essas mesmas propriedades. Isso garante que a função não seja interrompida quando for chamada com o resultado de uma redução anterior.
  • Não faça suposições com base no número de valores ele aceita. Não é garantido que os values parâmetro contém todos os valores para a chave fornecida. Então, usando values.length em cálculos é muito arriscado e deve ser evitado.

Atualização: As duas etapas abaixo não são necessárias (ou mesmo possíveis, não verifiquei) nas versões mais recentes do MongoDB. Ele agora pode lidar com essas etapas para você, se você especificar uma coleção de saída nas opções de redução de mapa:
{ out: { reduce: "tempResult" } }

Se sua função de redução for idempotente, você não deverá ter problemas para reduzir várias coleções de mapa. Basta reduzir novamente os resultados de cada coleta:

Etapa 1


Execute o map-reduce em cada coleção necessária e salve os resultados em uma única coleção temporária. Você pode armazenar os resultados usando uma função finalize:
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 })

Etapa 2


Execute outro map-reduce na coleção temporária, usando a mesma função de redução . A função map é uma função simples que seleciona as chaves e valores da coleção temporária:
map = function () {
  emit(this._id, this.value);
}

db.tempResult.mapReduce(map, reduce)

Este segundo map-reduce é basicamente um re-reduce e deve fornecer os resultados que você precisa.