Nota
Pipeline de agregación como alternativa a Map-Reduce
A partir de MongoDB 5.0, El map-reduce está en desuso:
En lugar de map-reduce, debería usar una canalización de agregación. Las canalizaciones de agregación ofrecen mejor rendimiento y usabilidad que map-reduce.
Puedes reescribir las operaciones de map-reduce usando etapas del pipeline de agregación, como
$group,$mergey otros.Para las operaciones map-reduce que requieren una funcionalidad personalizada, puedes utilizar los operadores de agregación
$accumulatory$function. Puedes utilizar esos operadores para definir expresiones de agregación personalizadas en JavaScript.
Para ejemplos de alternativas de pipeline de agregación a map-reduce, consulte:
Definición
mapReduceEl comando le
mapReducepermite ejecutar operaciones de agregación de mapa-reducción en una colección.Tip
En
mongosh, este comando también se puede ejecutar a través del método asistentemapReduce().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.
Compatibilidad
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.
Sintaxis
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> } )
Campos de comandos
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 Las vistas no dan soporte a operaciones de map-reduce. | |||||||||||
JavaScript o string | Una función JavaScript que asocia o "mapea" un 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 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 | |||||||||||
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 | |||||||||||
JavaScript o string | Opcional. Una función de JavaScript que modifica la salida después de la 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 | |||||||||||
booleano | Opcional. Especifica si se debe convertir los datos intermedios al formato BSON entre la ejecución de las funciones Se establece por defecto en En caso de que
En caso de que
| |||||||||||
booleano | opcional. Especifica si se debe incluir la información Se establece por defecto en Esta opción no se tiene en cuenta. La información de los resultados siempre excluye la información de | |||||||||||
booleano | Opcional. Permite que Si la opción de salida se establece | |||||||||||
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: Al especificar la intercalación, el campo Si no se especifica la intercalación, pero la colección tiene una intercalación por defecto (ver 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. | |||||||||||
| non-negative integer | Opcional. Especifica un límite de tiempo en milisegundos. Si no especifica un valor para MongoDB finaliza las operaciones que exceden su límite de tiempo asignado utilizando el mismo mecanismo que | ||||||||||
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. | |||||||||||
| 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.). |
Uso
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.
Requisitos para la función de map
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 comothisdentro de la función.La función
mapno debe acceder a la base de datos por ningún motivo.La función
mapdebe ser pura, o no tener ningún impacto fuera de la función (es decir, efectos secundarios.)La función
mappuede, opcionalmente, llamar aemit(key,value)cualquier número de veces para crear un documento de salida que asociekeyconvalue.
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); }); }
Requisitos para la función de reduce
La función reduce tiene el siguiente prototipo:
function(key, values) { ... return result; }
La función reduce exhibe los siguientes comportamientos:
La
reducefunción no debe acceder a la base de datos, ni siquiera para realizar operaciones de lectura.La función
reduceno debe afectar el sistema ajeno.MongoDB puede invocar la función
reducemás de una vez para la misma clave. En este caso, la salida anterior de la funciónreducepara esa clave se convertirá en uno de los valores de entrada para la siguiente invocación de la funciónreducepara esa clave.La función
reducepuede acceder a las variables definidas en el parámetroscope.Las entradas para
reduceno 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 dereduce.
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
valueemitido por la funciónmap.la función
reducedebe ser asociativa. La siguiente instrucción debe ser verdadera:reduce(key, [ C, reduce(key, [ A, B ]) ] ) == reduce( key, [ C, A, B ] ) la función
reducedebe ser idempotente. Garantice que la siguiente instrucción sea verdadera:reduce( key, [ reduce(key, valuesArray) ] ) == reduce( key, valuesArray ) la función
reducedebe ser conmutativa: es decir, que el orden de los elementos en elvaluesArrayno debe afectar el resultado de la funciónreduce, de modo que la siguiente instrucción sea verdadera:reduce( key, [ A, B ] ) == reduce( key, [ B, A ] )
Requisitos para la función de finalize
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
finalizeno debe acceder a la base de datos por ningún motivo.La función
finalizedebe ser pura, o no tener ningún impacto fuera de la función (es decir, efectos secundarios.)La función
finalizepuede acceder a las variables definidas en el parámetroscope.
out opciones
Puede especificar las siguientes opciones para el parámetro out:
Salida a una colección
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>
Salida a una colección con una acción
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:replaceReemplace el contenido de la
<collectionName>si la colección con la<collectionName>existe.mergeCombina 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.
reduceFusiona 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
reducetanto 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.
Salida Inline
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.
Acceso requerido
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.
Restricciones
El comando mapReduce ya no admite afterClusterTime. Como tal, mapReduce no se puede asociar con sesiones causalmente coherentes.
Ejemplos de Map-Reduce
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" } ])
Devolver el precio total por cliente
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:
Defina la función de mapeo para procesar cada documento de entrada:
En la función,
thisse refiere al documento que la operación de map-reduce está procesando.La función asigna
priceacust_idpara cada documento y emitecust_idyprice.
var mapFunction1 = function() { emit(this.cust_id, this.price); }; Define la función de reducción correspondiente con dos argumentos
keyCustIdyvaluesPrices:El
valuesPriceses un arreglo cuyos elementos son los valorespriceemitidos por la función map y agrupados porkeyCustId.La función reduce la matriz
valuesPricea la suma de sus elementos.
var reduceFunction1 = function(keyCustId, valuesPrices) { return Array.sum(valuesPrices); }; Realiza map-reduce en todos los documentos de la colección
ordersutilizando la función de mapeomapFunction1y la función de reducciónreduceFunction1: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ónmap_reduce_exampleya existe, la operación reemplazará el contenido con los resultados de esta operación de map-reduce.Query la colección
map_reduce_examplepara 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 }
Alternativa de agregación
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" } ])
La
$groupetapacust_idagrupa por y calcula elvaluecampo (véase también).$sumElvaluecampo contiene el totalpricede paracust_idcada.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 } A continuación, la
$outescribe la salida en la colecciónagg_alternative_1. Alternativamente, podrías usar$mergeen lugar de$out.Query la colección
agg_alternative_1para 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.
Calcular el pedido y la cantidad total con la cantidad promedio por artículo
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:
Agrupa por el campo
item.skuy calcula el número de órdenes y la cantidad total ordenada para cadasku.Calcula la cantidad promedio por pedido para cada valor de
skuy 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:
Defina la función de mapeo para procesar cada documento de entrada:
En la función,
thisse refiere al documento que la operación de map-reduce está procesando.Para cada elemento, la función asocia el
skucon un nuevo objetovalueque contiene elcountde1y el elementoqtypara la orden y emite elsku(almacenado en elkey) y elvalue.
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); } }; Define la función de reducción correspondiente con dos argumentos
keySKUycountObjVals:countObjValses un arreglo cuyos elementos son los objetos asignados a los valores agrupadoskeySKUpasados por la función map a la función reducer.La función reduce el arreglo
countObjValsa un solo objetoreducedValueque contiene los camposcountyqty.En
reducedVal, el campocountcontiene la suma de loscountcampos de los elementos individuales de la matriz, y el campoqtycontiene la suma de losqtycampos 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; }; Define una función de finalización con dos argumentos
keyyreducedVal. La función modifica el objetoreducedValpara añadir un campo calculado llamadoavgy devuelve el objeto modificado:var finalizeFunction2 = function (key, reducedVal) { reducedVal.avg = reducedVal.qty/reducedVal.count; return reducedVal; }; Realice la operación map-reduce en la colección
ordersutilizando las funcionesmapFunction2,reduceFunction2yfinalizeFunction2: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
querypara seleccionar solo los documentos con un valorord_datemayor o igual anew Date("2020-03-01"). Luego, envía los resultados a una colecciónmap_reduce_example2.Si la colección
map_reduce_example2ya 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.Query la colección
map_reduce_example2para 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 } }
Alternativa de agregación
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" } } ] )
La etapa
$matchselecciona únicamente aquellos documentos conord_datemayor o igual anew Date("2020-03-01").La etapa
$unwinddesglosa el documento por el campo de arregloitemspara 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" } ... La etapa
$groupagrupa por elitems.sku, calculando para cada sku:- El campo
qty. El campoqtycontiene la - total de
qtypedidos por cadaitems.sku(consultar$sum).
- El campo
- El arreglo
orders_ids. El campoorders_idscontiene un - matriz de órdenes distintos
_idpara elitems.sku$addToSet(ver).
- El arreglo
{ "_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 ] } La etapa modifica el documento de salida para reflejar la salida de map-reduce y tener dos
$projectcampos:_idvaluey. La$projectetapa establece:La etapa
$unwinddesglosa el documento por el campo de arregloitemspara 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" } ... La etapa
$groupagrupa por elitems.sku, calculando para cada sku:El
qtycampo. Elqtycampo contiene el total deqtypedidos por cadaitems.sku$sumutilizando.El arreglo
orders_ids. El campoorders_idscontiene un arreglo de diferentes órdenes_idpara elitems.skuusando$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 ] } La etapa modifica el documento de salida para reflejar la salida de map-reduce y tener dos
$projectcampos:_idvaluey. La$projectetapa establece:el
value.countal tamaño del arregloorders_idsutilizando$size.value.qtyal campoqtydel documento de entrada.el
value.avgal número promedio de unidades por pedido utilizando$dividey$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 } } Finalmente, el
$mergeescribe la salida en la colecciónagg_alternative_3. Si un documento existente tiene la misma clave_idque 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.Query la colección
agg_alternative_3para 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 obtener más información y ejemplos, consulte la página Map-Reduce y Realizar un Map-Reduce incremental.
Salida
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.resultsPara la salida escrita en línea, una matriz de documentos resultantes. Cada documento resultante contiene dos campos:
_idel campo contiene el valorkey,valueeste campo contiene el valor reducido o finalizado para elkeyasociado.
mapReduce.okUn valor de
1indica que el comando se ejecutó correctamente. Un valormapReducede0indica 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:
$clusterTimeyoperationTime.para clústeres fragmentados:
operationTimey$clusterTime.
Se puede consultar db.runCommand Response para obtener más información sobre estos campos.