sql >> Base de Datos >  >> NoSQL >> MongoDB

MongoDB mapear/reducir sobre múltiples colecciones?

Una función de reducción se puede llamar una vez, con una clave y todos los valores correspondientes (pero solo si hay múltiples valores para la clave; no se llamará en absoluto si solo hay 1 valor para la clave).

También se puede llamar varias veces, cada vez con una clave y solo un subconjunto de los valores correspondientes , y los resultados de reducción anteriores para esa tecla. Este escenario se llama re-reduce . Para admitir re-reduces, su función de reducción debe ser idempotente.

Hay dos características clave en una función de reducción idempotente:

  • El valor de retorno de la función de reducción debe tener el mismo formato que los valores toma. Entonces, si su función de reducción acepta una matriz de cadenas, la función debería devolver una cadena. Si acepta objetos con varias propiedades, debería devolver un objeto que contenga esas mismas propiedades. Esto asegura que la función no se interrumpa cuando se llama con el resultado de una reducción anterior.
  • No haga suposiciones basadas en la cantidad de valores que recibe. No se garantiza que los values el parámetro contiene todos los valores para la clave dada. Entonces usando values.length en los cálculos es muy arriesgado y debe evitarse.

Actualización: Los dos pasos a continuación no son necesarios (o incluso posibles, no lo he comprobado) en las versiones más recientes de MongoDB. Ahora puede manejar estos pasos por usted, si especifica una colección de salida en las opciones de reducción de mapa:

{ out: { reduce: "tempResult" } }

Si su función de reducción es idempotente, no debería tener problemas para reducir múltiples colecciones. Simplemente vuelva a reducir los resultados de cada colección:

Paso 1

Ejecute map-reduce en cada colección requerida y guarde los resultados en una única colección temporal. Puede almacenar los resultados utilizando una función de finalización:

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 })

Paso 2

Ejecute otro map-reduce en la colección temporal, usando la misma función de reducción . La función map es una función simple que selecciona las claves y valores de la colección temporal:

map = function () {
  emit(this._id, this.value);
}

db.tempResult.mapReduce(map, reduce)

Este segundo map-reduce es básicamente una re-reducción y debería darte los resultados que necesitas.