Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
Docs Menu
Docs Home
/ /

mapReduce (comando de base de datos)

Nota

Pipeline de agregación como alternativa a Map-Reduce

A partir de MongoDB 5.0, El map-reduce está en desuso:

Para ejemplos de alternativas de pipeline de agregación a map-reduce, consulte:

mapReduce

La mapReduce comando permite ejecutar operaciones de agregación map-reduce sobre una colección.

Tip

En mongosh, este comando también se puede ejecutar a través del método asistente mapReduce().

Los métodos asistente son convenientes para usuarios de mongosh, pero es posible que no proporcionen el mismo nivel de información que los comandos de base de datos. En los casos en que no se necesite la conveniencia o se requieran campos de retorno adicionales, utiliza el comando de base de datos.

Este comando está disponible en implementaciones alojadas en los siguientes entornos:

  • MongoDB Atlas: El servicio totalmente gestionado para implementaciones de MongoDB en la nube

Importante

Este comando no es compatible con los clústeres M0 y Flex. Para obtener más información, consulta Comandos no compatibles.

  • MongoDB Enterprise: La versión basada en suscripción y autogestionada de MongoDB

  • MongoDB Community: La versión de MongoDB con código fuente disponible, de uso gratuito y autogestionada.

Nota

MongoDB ignora la opción verbose.

A partir de la versión 4.2, MongoDB desaprueba:

  • La opción de map-reduce para crear una nueva colección particionada, así como el uso de la opción particionada para map-reduce. Para enviar a una colección particionada, primero crea la colección particionada. MongoDB 4.2 también desaprueba el reemplazo de una colección particionada existente.

El comando tiene la siguiente sintaxis:

db.runCommand(
{
mapReduce: <string>,
map: <string or JavaScript>,
reduce: <string or JavaScript>,
finalize: <string or JavaScript>,
out: <output>,
query: <document>,
sort: <document>,
limit: <number>,
scope: <document>,
jsMode: <boolean>,
verbose: <boolean>,
bypassDocumentValidation: <boolean>,
collation: <document>,
maxTimeMS: <integer>,
writeConcern: <document>,
comment: <any>
}
)

El comando toma los siguientes campos como argumentos:

Campo
Tipo
Descripción

string

El nombre de la colección en la que deseas realizar la operación de map-reduce. Esta colección será filtrada utilizando query antes de ser procesada por la función map.

Las vistas no dan soporte a operaciones de map-reduce.

JavaScript o string

Una función de JavaScript que asocia o "mapea" un value con un key y emite el key y el valor pair. Puedes especificar la función como tipo BSON Javascript (BSON Type 13) o String (BSON Type 2).

Para obtener más información, consulte Requisitos para la función de mapa.

JavaScript o string

Una función de JavaScript que reduce a un solo objeto todos los values asociados a un key específico. Puede especificar la función como JavaScript de tipo BSON (BSON Tipo 13) o String (BSON Tipo 2).

Para obtener más información, consulte Requisitos para la función de reducción.

string o documento

Especifica dónde exportar el resultado de la operación map-reduce. Puedes emitir a una colección o devolver el resultado en línea. En un primario de un set de réplicas puede enviar la salida a una colección o en línea, mientras que en un secundario, solo se puede realizar la salida en línea.

Para obtener más información, consulta Opciones de salida.

Documento

opcional. Especifica los criterios de selección utilizando operadores del query para determinar los documentos de entrada para la función map.

Documento

opcional. Ordena los documentos de entrada. Esta opción es útil para la optimización. Por ejemplo, indica que la clave de ordenamiento sea la misma que la clave de emisión para que haya menos operaciones de reducción. La clave de ordenamiento debe estar en un índice existente para esta colección.

Número

Opcional. Especifica un número máximo de documentos para la entrada a la función map.

JavaScript o string

opcional. Una función de JavaScript que modifica el resultado después de la función reduce. Puedes especificar la función como tipo BSON JavaScript (Tipo BSON 13) o String (Tipo BSON 2).

Para más información, consulte Requisitos para la función Finalizar.

Documento

Opcional. Especifica las variables globales a las que se puede acceder en las funciones map, reduce y finalize.

booleano

Opcional. Especifica si se debe convertir los datos intermedios al formato BSON entre la ejecución de las funciones map y reduce.

Se establece por defecto en false.

En caso de que false:

  • Internamente, MongoDB convierte los objetos JavaScript emitidos por la función map en objetos BSON. Estos objetos BSON se convierten posteriormente en objetos JavaScript al invocar la función reduce.

  • La operación de map-reduce coloca los objetos intermedios BSON en un almacenamiento temporal en disco. Esto permite que la operación map-reduce se ejecute con conjuntos de datos arbitrariamente grandes.

En caso de que true:

  • Internamente, los objetos JavaScript generados durante la función map permanecen como objetos JavaScript. No hay necesidad de convertir los objetos para la función reduce, lo que puede resultar en una ejecución más rápida.

  • Solo puedes usar jsMode para conjuntos de resultados con menos de 500,000 argumentos key distintos para la función emit() del mapeador.

booleano

opcional. Especifica si se debe incluir la información timing en la información del resultado. Establezca verbose en true para incluir la información de timing.

Se establece por defecto en false.

Esta opción no se tiene en cuenta. La información de los resultados siempre excluye la información de timing. Se puede ver la información de temporización ejecutando explain el comando mapReduce en las "executionStats" o "allPlansExecution" verbosity modas.

booleano

Opcional. Permite que mapReduce omita la validación de esquema durante la operación. Esto permite insertar documentos que no cumplen con los requisitos de validación.

Si la opción de salida se establece inline en, no se realiza ninguna validación del esquema. Si la salida se dirige a una colección, cumple las reglas de validación de la colección y no inserta ningún documento no válido a menos quemapReduce el bypassDocumentValidation parámetro se establezca en verdadero.

Documento

Opcional.

Especifica la intercalación a utilizar para la operación.

La intercalación permite a los usuarios especificar reglas propias del lenguaje para la comparación de strings, como reglas para el uso de mayúsculas y minúsculas y marcas de acento.

La opción de intercalación tiene la siguiente sintaxis:

collation: {
locale: <string>,
caseLevel: <boolean>,
caseFirst: <string>,
strength: <int>,
numericOrdering: <boolean>,
alternate: <string>,
maxVariable: <string>,
backwards: <boolean>
}

Al especificar la intercalación, el campo locale es obligatorio; todos los demás campos de intercalación son opcionales. Para las descripciones de los campos, consulta Documento de intercalación.

Si no se especifica la intercalación, pero la colección tiene una intercalación por defecto (ver db.createCollection()), la operación utiliza la intercalación especificada para la colección.

Si no se especifica ninguna intercalación para la colección o para las operaciones, MongoDB utiliza la comparación binaria simple usada en versiones anteriores para las comparaciones de strings.

No puedes especificar varias intercalaciones para una operación. Por ejemplo, no puedes especificar diferentes intercalaciones por campo, o si realizas una búsqueda con un ordenamiento, no puedes usar una intercalación para la búsqueda y otra para el ordenamiento.

maxTimeMS

non-negative integer

Opcional.

Especifica un límite de tiempo en milisegundos. Si no especifica un valor para maxTimeMS, las operaciones no agotarán el tiempo de espera. Un valor de 0 especifica explícitamente el comportamiento por defecto sin límites.

MongoDB finaliza las operaciones que exceden su límite de tiempo asignado utilizando el mismo mecanismo que db.killOp(). MongoDB solo termina una operación en uno de sus puntos de interrupción designados.

Documento

opcional. Un documento que expresa el nivel de confirmación de escritura (write concern) que se debe utilizar al enviar datos a una colección. Omitir para utilizar el nivel de confirmación de escritura (write concern) por defecto.

comment

any

Opcional. Un comentario proporcionado por el usuario para adjuntar a este comando. Una vez configurado, este comentario aparece junto a los registros de este comando en las siguientes ubicaciones:

Un comentario puede ser de cualquier tipo BSON válido (string, objeto, arreglo, etc.).

Lo siguiente es un prototipo de uso del comando mapReduce:

var mapFunction = function() { ... };
var reduceFunction = function(key, values) { ... };
db.runCommand(
{
mapReduce: <input-collection>,
map: mapFunction,
reduce: reduceFunction,
out: { merge: <output-collection> },
query: <query>
}
)

Nota

JavaScript en MongoDB

Aunque mapReduce utiliza JavaScript, la mayoría de las interacciones con MongoDB no utilizan JavaScript, sino que emplean un driver idiomático en el lenguaje de la aplicación que interactúa.

La función map se encarga de transformar cada documento de entrada en cero o más documentos. Puede acceder a las variables definidas en el parámetro scope y tiene el siguiente prototipo:

function() {
...
emit(key, value);
}

La función map tiene los siguientes requisitos:

  • En la función map, hace referencia al documento actual como this dentro de la función.

  • La función map no debe acceder a la base de datos por ningún motivo.

  • La función map debe ser pura, o no tener ningún impacto fuera de la función (es decir, efectos secundarios.)

  • La función map puede, opcionalmente, llamar a emit(key,value) cualquier número de veces para crear un documento de salida que asocie key con value.

La siguiente función map llamará a emit(key,value) 0 o 1 veces dependiendo del valor del campo status del documento de entrada:

function() {
if (this.status == 'A')
emit(this.cust_id, 1);
}

La siguiente función map puede llamar a emit(key,value) varias veces dependiendo del número de elementos en el campo items del documento de entrada:

function() {
this.items.forEach(function(item){ emit(item.sku, 1); });
}

La función reduce tiene el siguiente prototipo:

function(key, values) {
...
return result;
}

La función reduce exhibe los siguientes comportamientos:

  • La reduce función no debe acceder a la base de datos, ni siquiera para realizar operaciones de lectura.

  • La función reduce no debe afectar el sistema ajeno.

  • MongoDB puede invocar la función reduce más de una vez para la misma clave. En este caso, la salida anterior de la función reduce para esa clave se convertirá en uno de los valores de entrada para la siguiente invocación de la función reduce para esa clave.

  • La función reduce puede acceder a las variables definidas en el parámetro scope.

  • Las entradas para reduce no deben ser mayores a la mitad del tamaño máximo de documento BSON de MongoDB. Este requisito podría no cumplirse cuando se devuelven documentos grandes y luego se combinan en pasos posteriores de reduce.

Debido a que es posible invocar la función reduce más de una vez para la misma clave, las siguientes propiedades deben ser verdaderas:

  • el tipo del objeto de retorno debe ser idéntico al tipo del value emitido por la función map.

  • la función reduce debe ser asociativa. La siguiente instrucción debe ser verdadera:

    reduce(key, [ C, reduce(key, [ A, B ]) ] ) == reduce( key, [ C, A, B ] )
  • la función reduce debe ser idempotente. Garantice que la siguiente instrucción sea verdadera:

    reduce( key, [ reduce(key, valuesArray) ] ) == reduce( key, valuesArray )
  • la función reduce debe ser conmutativa: es decir, que el orden de los elementos en el valuesArray no debe afectar el resultado de la función reduce, de modo que la siguiente instrucción sea verdadera:

    reduce( key, [ A, B ] ) == reduce( key, [ B, A ] )

La función finalize tiene el siguiente prototipo:

function(key, reducedValue) {
...
return modifiedObject;
}

La función finalize recibe como argumentos un valor key y el reducedValue de la función reduce. Ten en cuenta que:

  • La función finalize no debe acceder a la base de datos por ningún motivo.

  • La función finalize debe ser pura, o no tener ningún impacto fuera de la función (es decir, efectos secundarios.)

  • La función finalize puede acceder a las variables definidas en el parámetro scope.

Puede especificar las siguientes opciones para el parámetro out:

Esta opción genera la salida en una nueva colección y no está disponible en los miembros secundarios de sets de réplicas.

out: <collectionName>

Nota

A partir de la versión 4.2, MongoDB desaprueba:

  • La opción de map-reduce para crear una nueva colección particionada, así como el uso de la opción particionada para map-reduce. Para enviar a una colección particionada, primero crea la colección particionada. MongoDB 4.2 también desaprueba el reemplazo de una colección particionada existente.

Esta opción solo está disponible al transferir una colección ya existente a out. No está disponible en miembros secundarios de conjuntos de réplicas.

out: { <action>: <collectionName>
[, db: <dbName>]
[, sharded: <boolean> ] }

Cuando se envía una salida a una colección con una acción, el out tiene los siguientes parámetros:

  • <action>Especifique una de las siguientes acciones:

    • replace

      Reemplace el contenido de la <collectionName> si la colección con la <collectionName> existe.

    • merge

      Combina el nuevo resultado con el resultado existente si la colección de salida ya existe. Si un documento existente tiene la misma clave que el nuevo resultado, sobrescribe ese documento existente.

    • reduce

      Fusiona el nuevo resultado con el resultado existente si la colección de salida ya existe. Si un documento existente tiene la misma clave que el nuevo resultado, aplica la función reduce tanto a los documentos nuevos como a los existentes y sobrescribe el documento existente con el resultado.

  • db:

    opcional. El nombre de la base de datos en la que deseas que la operación de map-reduce guarde su resultado. Por defecto, esta será la misma base de datos que la colección de entrada.

Realice la operación de map-reduce en la memoria y devuelva el resultado. Esta opción es la única opción disponible para out en los miembros secundarios de los set de réplicas.

out: { inline: 1 }

El resultado debe ajustarse al tamaño máximo de un documento BSON.

Si tu implementación de MongoDB aplica autenticación, el usuario que ejecuta el comando mapReduce debe poseer las siguientes acciones de privilegio:

Map-reduce con la opción de salida {out : inline}:

Map-reduce con la acción replace al exportar a una colección:

map-reduce con las acciones merge o reduce al salida a una colección:

La readWrite función integrada proporciona los permisos necesarios para realizar la agregación de mapas y reducciones.

El comando mapReduce ya no admite afterClusterTime. Como tal, mapReduce no se puede asociar con sesiones causalmente coherentes.

Enmongosh, el métododb.collection.mapReduce()envuelve el comandomapReduce. Los siguientes ejemplos utilizan el métododb.collection.mapReduce():

Los ejemplos de esta sección incluyen alternativas de pipelines de agregación sin expresiones de agregación personalizadas. Para alternativas que usan expresiones personalizadas, consulta Ejemplos de traducción del antiguo map-reduce al pipeline de agregación.

Crea una colección de muestra orders con estos documentos:

db.orders.insertMany([
{ _id: 1, cust_id: "Ant O. Knee", ord_date: new Date("2020-03-01"), price: 25, items: [ { sku: "oranges", qty: 5, price: 2.5 }, { sku: "apples", qty: 5, price: 2.5 } ], status: "A" },
{ _id: 2, cust_id: "Ant O. Knee", ord_date: new Date("2020-03-08"), price: 70, items: [ { sku: "oranges", qty: 8, price: 2.5 }, { sku: "chocolates", qty: 5, price: 10 } ], status: "A" },
{ _id: 3, cust_id: "Busby Bee", ord_date: new Date("2020-03-08"), price: 50, items: [ { sku: "oranges", qty: 10, price: 2.5 }, { sku: "pears", qty: 10, price: 2.5 } ], status: "A" },
{ _id: 4, cust_id: "Busby Bee", ord_date: new Date("2020-03-18"), price: 25, items: [ { sku: "oranges", qty: 10, price: 2.5 } ], status: "A" },
{ _id: 5, cust_id: "Busby Bee", ord_date: new Date("2020-03-19"), price: 50, items: [ { sku: "chocolates", qty: 5, price: 10 } ], status: "A"},
{ _id: 6, cust_id: "Cam Elot", ord_date: new Date("2020-03-19"), price: 35, items: [ { sku: "carrots", qty: 10, price: 1.0 }, { sku: "apples", qty: 10, price: 2.5 } ], status: "A" },
{ _id: 7, cust_id: "Cam Elot", ord_date: new Date("2020-03-20"), price: 25, items: [ { sku: "oranges", qty: 10, price: 2.5 } ], status: "A" },
{ _id: 8, cust_id: "Don Quis", ord_date: new Date("2020-03-20"), price: 75, items: [ { sku: "chocolates", qty: 5, price: 10 }, { sku: "apples", qty: 10, price: 2.5 } ], status: "A" },
{ _id: 9, cust_id: "Don Quis", ord_date: new Date("2020-03-20"), price: 55, items: [ { sku: "carrots", qty: 5, price: 1.0 }, { sku: "apples", qty: 10, price: 2.5 }, { sku: "oranges", qty: 10, price: 2.5 } ], status: "A" },
{ _id: 10, cust_id: "Don Quis", ord_date: new Date("2020-03-23"), price: 25, items: [ { sku: "oranges", qty: 10, price: 2.5 } ], status: "A" }
])

Realice la operación map-reduce en la colección orders para agrupar por cust_id y calcular la suma de price para cada cust_id:

  1. Defina la función de mapeo para procesar cada documento de entrada:

    • En la función, this se refiere al documento que la operación de map-reduce está procesando.

    • La función asigna price a cust_id para cada documento y emite cust_id y price.

    var mapFunction1 = function() {
    emit(this.cust_id, this.price);
    };
  2. Define la función de reducción correspondiente con dos argumentos keyCustId y valuesPrices:

    • El valuesPrices es un arreglo cuyos elementos son los valores price emitidos por la función map y agrupados por keyCustId.

    • La función reduce la matriz valuesPrice a la suma de sus elementos.

    var reduceFunction1 = function(keyCustId, valuesPrices) {
    return Array.sum(valuesPrices);
    };
  3. Realiza map-reduce en todos los documentos de la colección orders utilizando la función de mapeo mapFunction1 y la función de reducción reduceFunction1:

    db.orders.mapReduce(
    mapFunction1,
    reduceFunction1,
    { out: "map_reduce_example" }
    )

    Esta operación envía los resultados a una colección llamada map_reduce_example. Si la colección map_reduce_example ya existe, la operación reemplazará el contenido con los resultados de esta operación de map-reduce.

  4. Query la colección map_reduce_example para verificar los resultados:

    db.map_reduce_example.find().sort( { _id: 1 } )

    La operación devuelve estos documentos:

    { "_id" : "Ant O. Knee", "value" : 95 }
    { "_id" : "Busby Bee", "value" : 125 }
    { "_id" : "Cam Elot", "value" : 60 }
    { "_id" : "Don Quis", "value" : 155 }

Utilizando los operadores de la pipeline de agregación disponibles, se puede reescribir la operación de map-reduce sin definir funciones personalizadas:

db.orders.aggregate([
{ $group: { _id: "$cust_id", value: { $sum: "$price" } } },
{ $out: "agg_alternative_1" }
])
  1. La $group etapa cust_id agrupa por y calcula el value campo (véase también).$sum El value campo contiene el total price de para cust_id cada.

    La etapa generó los siguientes documentos para la etapa siguiente:

    { "_id" : "Don Quis", "value" : 155 }
    { "_id" : "Ant O. Knee", "value" : 95 }
    { "_id" : "Cam Elot", "value" : 60 }
    { "_id" : "Busby Bee", "value" : 125 }
  2. A continuación, la $out escribe la salida en la colección agg_alternative_1. Alternativamente, podrías usar $merge en lugar de $out.

  3. Query la colección agg_alternative_1 para verificar los resultados:

    db.agg_alternative_1.find().sort( { _id: 1 } )

    La operación devuelve los siguientes documentos:

    { "_id" : "Ant O. Knee", "value" : 95 }
    { "_id" : "Busby Bee", "value" : 125 }
    { "_id" : "Cam Elot", "value" : 60 }
    { "_id" : "Don Quis", "value" : 155 }

Tip

Para una alternativa que utiliza expresiones de agregación personalizadas, consulte Ejemplos de traducción de map-reduce a la pipeline de agregación.

En el siguiente ejemplo, se verá una operación de map-reduce en la colección orders para todos los documentos que tengan un valor de ord_date mayor o igual a 2020-03-01.

La operación en el ejemplo:

  1. Agrupa por el campo item.sku y calcula el número de órdenes y la cantidad total ordenada para cada sku.

  2. Calcula la cantidad promedio por pedido para cada valor de sku y fusiona los resultados en la colección de salida.

Al fusionar resultados, si un documento existente tiene la misma clave que el nuevo resultado, la operación lo sobrescribe. Si no existe ningún documento con la misma clave, la operación lo inserta.

Ejemplo de pasos:

  1. Defina la función de mapeo para procesar cada documento de entrada:

    • En la función, this se refiere al documento que la operación de map-reduce está procesando.

    • Para cada elemento, la función asocia el sku con un nuevo objeto value que contiene el count de 1 y el elemento qty para la orden y emite el sku (almacenado en el key) y el value.

    var mapFunction2 = function() {
    for (var idx = 0; idx < this.items.length; idx++) {
    var key = this.items[idx].sku;
    var value = { count: 1, qty: this.items[idx].qty };
    emit(key, value);
    }
    };
  2. Define la función de reducción correspondiente con dos argumentos keySKU y countObjVals:

    • countObjVals es un arreglo cuyos elementos son los objetos asignados a los valores agrupados keySKU pasados por la función map a la función reducer.

    • La función reduce el arreglo countObjVals a un solo objeto reducedValue que contiene los campos count y qty.

    • En reducedVal, el campo count contiene la suma de los count campos de los elementos individuales de la matriz, y el campo qty contiene la suma de los qty campos de los elementos individuales de la matriz.

    var reduceFunction2 = function(keySKU, countObjVals) {
    reducedVal = { count: 0, qty: 0 };
    for (var idx = 0; idx < countObjVals.length; idx++) {
    reducedVal.count += countObjVals[idx].count;
    reducedVal.qty += countObjVals[idx].qty;
    }
    return reducedVal;
    };
  3. Define una función de finalización con dos argumentos key y reducedVal. La función modifica el objeto reducedVal para añadir un campo calculado llamado avg y devuelve el objeto modificado:

    var finalizeFunction2 = function (key, reducedVal) {
    reducedVal.avg = reducedVal.qty/reducedVal.count;
    return reducedVal;
    };
  4. Realice la operación map-reduce en la colección orders utilizando las funciones mapFunction2, reduceFunction2 y finalizeFunction2:

    db.orders.mapReduce(
    mapFunction2,
    reduceFunction2,
    {
    out: { merge: "map_reduce_example2" },
    query: { ord_date: { $gte: new Date("2020-03-01") } },
    finalize: finalizeFunction2
    }
    );

    Esta operación utiliza el campo query para seleccionar solo los documentos con un valor ord_date mayor o igual a new Date("2020-03-01"). Luego, envía los resultados a una colección map_reduce_example2.

    Si la colección map_reduce_example2 ya existe, la operación fusionará el contenido existente con los resultados de esta operación de map-reduce. Es decir, si un documento existente tiene la misma clave que el nuevo resultado, la operación sobrescribirá el documento existente. Si no existe un documento con la misma clave, la operación inserta el documento.

  5. Query la colección map_reduce_example2 para verificar los resultados:

    db.map_reduce_example2.find().sort( { _id: 1 } )

    La operación devuelve estos documentos:

    { "_id" : "apples", "value" : { "count" : 4, "qty" : 35, "avg" : 8.75 } }
    { "_id" : "carrots", "value" : { "count" : 2, "qty" : 15, "avg" : 7.5 } }
    { "_id" : "chocolates", "value" : { "count" : 3, "qty" : 15, "avg" : 5 } }
    { "_id" : "oranges", "value" : { "count" : 7, "qty" : 63, "avg" : 9 } }
    { "_id" : "pears", "value" : { "count" : 1, "qty" : 10, "avg" : 10 } }

Utilizando los operadores de la pipeline de agregación disponibles, se puede reescribir la operación de map-reduce sin definir funciones personalizadas:

db.orders.aggregate( [
{ $match: { ord_date: { $gte: new Date("2020-03-01") } } },
{ $unwind: "$items" },
{ $group: { _id: "$items.sku", qty: { $sum: "$items.qty" }, orders_ids: { $addToSet: "$_id" } } },
{ $project: { value: { count: { $size: "$orders_ids" }, qty: "$qty", avg: { $divide: [ "$qty", { $size: "$orders_ids" } ] } } } },
{ $merge: { into: "agg_alternative_3", on: "_id", whenMatched: "replace", whenNotMatched: "insert" } }
] )
  1. La etapa $match selecciona únicamente aquellos documentos con ord_date mayor o igual a new Date("2020-03-01").

  2. La etapa $unwind desglosa el documento por el campo de arreglo items para producir un documento por cada elemento del mismo. Por ejemplo:

    { "_id" : 1, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-01T00:00:00Z"), "price" : 25, "items" : { "sku" : "oranges", "qty" : 5, "price" : 2.5 }, "status" : "A" }
    { "_id" : 1, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-01T00:00:00Z"), "price" : 25, "items" : { "sku" : "apples", "qty" : 5, "price" : 2.5 }, "status" : "A" }
    { "_id" : 2, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 70, "items" : { "sku" : "oranges", "qty" : 8, "price" : 2.5 }, "status" : "A" }
    { "_id" : 2, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 70, "items" : { "sku" : "chocolates", "qty" : 5, "price" : 10 }, "status" : "A" }
    { "_id" : 3, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 50, "items" : { "sku" : "oranges", "qty" : 10, "price" : 2.5 }, "status" : "A" }
    { "_id" : 3, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 50, "items" : { "sku" : "pears", "qty" : 10, "price" : 2.5 }, "status" : "A" }
    { "_id" : 4, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-18T00:00:00Z"), "price" : 25, "items" : { "sku" : "oranges", "qty" : 10, "price" : 2.5 }, "status" : "A" }
    { "_id" : 5, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-19T00:00:00Z"), "price" : 50, "items" : { "sku" : "chocolates", "qty" : 5, "price" : 10 }, "status" : "A" }
    ...
  3. La etapa $group agrupa por el items.sku, calculando para cada sku:

    • El campo qty. El campo qty contiene la
      total de qty pedidos por cada items.sku (consultar $sum).
    • El arreglo orders_ids. El campo orders_ids contiene un
      matriz de órdenes distintos _id para el items.sku $addToSet(ver).
    { "_id" : "chocolates", "qty" : 15, "orders_ids" : [ 2, 5, 8 ] }
    { "_id" : "oranges", "qty" : 63, "orders_ids" : [ 4, 7, 3, 2, 9, 1, 10 ] }
    { "_id" : "carrots", "qty" : 15, "orders_ids" : [ 6, 9 ] }
    { "_id" : "apples", "qty" : 35, "orders_ids" : [ 9, 8, 1, 6 ] }
    { "_id" : "pears", "qty" : 10, "orders_ids" : [ 3 ] }
  4. La etapa modifica el documento de salida para reflejar la salida de map-reduce y tener dos $project campos:_id valuey. La $project etapa establece:

  5. La etapa $unwind desglosa el documento por el campo de arreglo items para producir un documento por cada elemento del mismo. Por ejemplo:

    { "_id" : 1, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-01T00:00:00Z"), "price" : 25, "items" : { "sku" : "oranges", "qty" : 5, "price" : 2.5 }, "status" : "A" }
    { "_id" : 1, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-01T00:00:00Z"), "price" : 25, "items" : { "sku" : "apples", "qty" : 5, "price" : 2.5 }, "status" : "A" }
    { "_id" : 2, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 70, "items" : { "sku" : "oranges", "qty" : 8, "price" : 2.5 }, "status" : "A" }
    { "_id" : 2, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 70, "items" : { "sku" : "chocolates", "qty" : 5, "price" : 10 }, "status" : "A" }
    { "_id" : 3, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 50, "items" : { "sku" : "oranges", "qty" : 10, "price" : 2.5 }, "status" : "A" }
    { "_id" : 3, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 50, "items" : { "sku" : "pears", "qty" : 10, "price" : 2.5 }, "status" : "A" }
    { "_id" : 4, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-18T00:00:00Z"), "price" : 25, "items" : { "sku" : "oranges", "qty" : 10, "price" : 2.5 }, "status" : "A" }
    { "_id" : 5, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-19T00:00:00Z"), "price" : 50, "items" : { "sku" : "chocolates", "qty" : 5, "price" : 10 }, "status" : "A" }
    ...
  6. La etapa $group agrupa por el items.sku, calculando para cada sku:

    • El qty campo. El qty campo contiene el total de qty pedidos por cada items.sku $sumutilizando.

    • El arreglo orders_ids. El campo orders_ids contiene un arreglo de diferentes órdenes _id para el items.sku usando $addToSet.

    { "_id" : "chocolates", "qty" : 15, "orders_ids" : [ 2, 5, 8 ] }
    { "_id" : "oranges", "qty" : 63, "orders_ids" : [ 4, 7, 3, 2, 9, 1, 10 ] }
    { "_id" : "carrots", "qty" : 15, "orders_ids" : [ 6, 9 ] }
    { "_id" : "apples", "qty" : 35, "orders_ids" : [ 9, 8, 1, 6 ] }
    { "_id" : "pears", "qty" : 10, "orders_ids" : [ 3 ] }
  7. La etapa modifica el documento de salida para reflejar la salida de map-reduce y tener dos $project campos:_id valuey. La $project etapa establece:

    • el value.count al tamaño del arreglo orders_ids utilizando $size.

    • value.qty al campo qty del documento de entrada.

    • el value.avg al número promedio de unidades por pedido utilizando $divide y $size.

    { "_id" : "apples", "value" : { "count" : 4, "qty" : 35, "avg" : 8.75 } }
    { "_id" : "pears", "value" : { "count" : 1, "qty" : 10, "avg" : 10 } }
    { "_id" : "chocolates", "value" : { "count" : 3, "qty" : 15, "avg" : 5 } }
    { "_id" : "oranges", "value" : { "count" : 7, "qty" : 63, "avg" : 9 } }
    { "_id" : "carrots", "value" : { "count" : 2, "qty" : 15, "avg" : 7.5 } }
  8. Finalmente, el $merge escribe la salida en la colección agg_alternative_3. Si un documento existente tiene la misma clave _id que el nuevo resultado, la operación sobrescribe el documento existente. Si no existe ningún documento con la misma clave, la operación inserta el documento.

  9. Query la colección agg_alternative_3 para verificar los resultados:

    db.agg_alternative_3.find().sort( { _id: 1 } )

    La operación devuelve los siguientes documentos:

    { "_id" : "apples", "value" : { "count" : 4, "qty" : 35, "avg" : 8.75 } }
    { "_id" : "carrots", "value" : { "count" : 2, "qty" : 15, "avg" : 7.5 } }
    { "_id" : "chocolates", "value" : { "count" : 3, "qty" : 15, "avg" : 5 } }
    { "_id" : "oranges", "value" : { "count" : 7, "qty" : 63, "avg" : 9 } }
    { "_id" : "pears", "value" : { "count" : 1, "qty" : 10, "avg" : 10 } }

Tip

Para una alternativa que utiliza expresiones de agregación personalizadas, consulte Ejemplos de traducción de map-reduce a la pipeline de agregación.

Para más información y ejemplos, consulte la página Map-Reduce y Ejecutar Map-Reduce incremental

Si configura el parámetro out para escribir los resultados en una colección, el comando devuelve un documento con el siguiente mapReduce formato:

{ "result" : "map_reduce_example", "ok" : 1 }

Si configuras el parámetro out para sacar los resultados en línea, el comando mapReduce devuelve un documento en la siguiente forma:

{
"results" : [
{
"_id" : <key>,
"value" :<reduced or finalizedValue for key>
},
...
],
"ok" : <int>
}
mapReduce.result

Para la salida enviada a una colección, este valor es uno de los siguientes:

  • un string para el nombre de la colección si salida no especifica el nombre de la base de datos, o

  • un documento con los campos db y collection, si out especificó tanto una base de datos como un nombre de colección.

mapReduce.results

Para la salida escrita en línea, una matriz de documentos resultantes. Cada documento resultante contiene dos campos:

  • _id el campo contiene el valor key,

  • value este campo contiene el valor reducido o finalizado para el key asociado.

mapReduce.ok

Un valor de 1 indica que el comando se ejecutó correctamente. Un valor mapReduce de 0 indica un error.

Además de los campos de retorno específicos del comando mencionados anteriormente, la db.runCommand() incluye información adicional:

  • para conjuntos de réplicas: $clusterTime y operationTime.

  • para clústeres fragmentados: operationTime y $clusterTime.

Se puede consultar db.runCommand Response para obtener más información sobre estos campos.

Volver

insert

En esta página