suma new array mongodb mapreduce pymongo

new - MongoDB MapReduce-Emitir una clave/un valor no reduce la llamada



mongodb project new field (5)

Así que soy nuevo con mongodb y mapreduce en general y me encontré con esta "peculiaridad" (o al menos en mi mente una peculiaridad)

Digamos que tengo objetos en mi colección así:

{''clave'': 5, ''valor'': 5}

{''clave'': 5, ''valor'': 4}

{''clave'': 5, ''valor'': 1}

{''clave'': 4, ''valor'': 6}

{''clave'': 4, ''valor'': 4}

{''clave'': 3, ''valor'': 0}

Mi función de mapa simplemente emite la clave y el valor

Mi función de reducción simplemente agrega los valores Y antes de devolverlos agrega 1 (Hice esto para ver si se llama la función de reducción)

Mis resultados siguen:

{''_id'': 3, ''valor'': 0 }

{''_id'': 4, ''valor'': 11.0}

{''_id'': 5, ''valor'': 11.0}

Como puede ver, para las claves 4 y 5 obtengo la respuesta esperada de 11 PERO para la clave 3 (con solo una entrada en la colección con esa clave) ¡Obtengo el 0 inesperado!

¿Es este el comportamiento natural de mapreduce en general? Para MongoDB? Para pymongo (que estoy usando)?


¿Es este el comportamiento natural de mapreduce en general?

Sí.



La función de reducción combina documentos con la misma clave en un documento. Si la función de mapa emite un solo documento para una clave en particular (como es el caso con la clave 3), no se llamará a la función de reducción.


Me doy cuenta de que esta es una pregunta más antigua, pero llegué a ella y sentí que aún no entendía por qué existe este comportamiento y cómo construir un mapa / reducir la funcionalidad, por lo que es un problema.

La razón por la que MongoDB no llama a la función de reducción si hay una sola instancia de una clave es porque no es necesaria (espero que esto tenga más sentido en un momento). Los siguientes son requisitos para funciones de reducción :

  • La función de reducción debe devolver un objeto cuyo tipo debe ser idéntico al tipo del valor emitido por la función de mapa.
  • El orden de los elementos en valuesArray no debe afectar la salida de la función de reducción
  • La función de reducción debe ser idempotente.

El primer requisito es muy importante y parece que muchas personas lo pasan por alto porque he visto a varias personas mapear en la función de reducción y luego tratar el caso de una sola tecla en la función de finalización. Sin embargo, esta es la forma incorrecta de abordar el problema.

Piénselo de esta manera: si solo hay una instancia de una clave, una optimización simple es omitir el reductor por completo (no hay nada que reducir). Los valores de una sola clave aún se incluyen en la salida, pero la intención del reductor es crear un resultado agregado de los documentos de varias claves en su colección. Si el asignador y el reductor emiten el mismo tipo, no debería darse cuenta de ello al observar la estructura de objetos del resultado de las funciones de reducción / mapa. No debería tener que usar una función de finalización para corregir la estructura de sus objetos que no se ejecutaron a través del reductor.

En resumen, realice su asignación en su función de mapa y reduzca los valores de varias claves en un único resultado agregado en sus funciones de reducción.


Solución:

  • nuevo campo agregado en el mapa : single: 0
  • en reducir cambiar este campo a: single: 1
  • Para finalizar, compruebe este campo y realice las acciones necesarias.

    $map = new MongoCode("function() { var value = { time: this.time, email_id: this.email_id, single: 0 }; emit(this.email, value); }"); $reduce = new MongoCode("function(k, vals) { // make some need actions here return { time: vals[0].time, email_id: vals[0].email_id, single: 1 }; }"); $finalize = new MongoCode("function(key, reducedVal) { if (reducedVal.single == 0) { reducedVal.time = 11111; } return reducedVal; };");