Menu Docs

Redução de mapa

Observação

Pipeline de Agregação como Alternativa à Redução de Mapa

A partir do MongoDB 5.0, map-reduce está obsoleto:

  • Em vez de map-reduce, você deve usar um aggregation pipeline. aggregation pipeline fornece melhor desempenho e usabilidade do que a redução de mapa.

  • Você pode reescrever operações de map-reduce utilizando aggregation pipeline stages, como $group, $merge e outros.

  • Nas operações de map-reduce que exigem funcionalidade personalizada, você pode usar os operadores de agregação $accumulator e $function. Você pode usar esses operadores para definir expressões de agregação personalizadas no JavaScript.

Para obter exemplos de alternativas de aggregation pipeline para map-reduce, consulte:

mapReduce

The mapReduce command allows you to run Mapear-Reduzir aggregation operations over a collection.

Dica

Em mongosh, esse comando também pode ser executado por meio do método auxiliar mapReduce().

Os métodos auxiliares são práticos para os usuários mongosh, mas podem não retornar o mesmo nível de informações que os comandos do banco de dados. Nos casos em que a praticidade não for necessária ou os campos de retorno adicionais forem necessários, use o comando de banco de dados.

Esse comando está disponível em implantações hospedadas nos seguintes ambientes:

  • MongoDB Atlas: o serviço totalmente gerenciado para implantações do MongoDB na nuvem

Importante

Este comando não é suportado em clusters M0, M2 e M5 . Para obter mais informações, consulte Comandos não suportados.

  • MongoDB Enterprise: a versão autogerenciada e baseada em assinatura do MongoDB

  • MongoDB Community: uma versão com código disponível, de uso gratuito e autogerenciada do MongoDB

Observação

MongoDB ignores the verbose option.

Starting in version 4.2, MongoDB deprecates:

  • The map-reduce option to criar a new sharded collection as well as the use of the sharded option for map-reduce. To output to a sharded collection, create the sharded collection first. MongoDB 4.2 also deprecates the replacement of an existing sharded collection.

O comando tem a seguinte sintaxe:

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

The command takes the following fields as arguments:

Campo
Tipo
Descrição

string

The name of the collection on which you want to perform map-reduce. This collection will be filtered using query before being processed by the map function.

As visualizações não suportam operações de redução de mapa.

JavaScript or String

A JavaScript function that associates or "maps" a value with a key and emits the key and value pair. You can specify the function as Tipo de BSON Javascript (BSON Type 13) or String (BSON Type 2).

For more information, see Requirements for the map Function.

JavaScript or String

A JavaScript function that "reduces" to a single object all the values associated with a particular key. You can specify the function as BSON type JavaScript (BSON Type 13) or String (BSON Type 2).

For more information, see Requirements for the reduce Function.

string ou documento

Specifies where to output the result of the map-reduce operation. You can either output to a collection or return the result inline. On a Principal member of a replica set you can output either to a collection or inline, but on a secundário, only inline output is possible.

For more information, see out Options.

documento

Optional. Specifies the selection criteria using query operators for determining the documents input to the map function.

documento

Optional. Sorts the Entrada documents. This option is useful for optimization. For example, specify the sort key to be the same as the emit key so that there are fewer reduce operations. The sort key must be in an existing index for this collection.

número

Optional. Specifies a maximum number of documents for the input into the map function.

JavaScript or String

Optional. A JavaScript function that modifies the output after the reduce function. You can specify the function as BSON type JavaScript (BSON Type 13) or String (BSON Type 2).

For more information, see Requirements for the finalize Function.

documento

Optional. Specifies global variables that are accessible in the map, reduce and finalize functions.

booleano

Optional. Specifies whether to convert intermediate data into BSON format between the execution of the map and reduce functions.

Padrão é false.

Se false:

  • Internally, MongoDB converts the JavaScript objects emitted by the map function to BSON objects. These BSON objects are then converted back to JavaScript objects when calling the reduce function.

  • The map-reduce operation places the intermediate BSON objects in temporary, on-disk storage. This allows the map-reduce operation to execute over arbitrarily large data sets.

Se true:

  • Internally, the JavaScript objects emitted during map function remain as JavaScript objects. There is no need to convert the objects for the reduce function, which can result in faster execution.

  • You can only use jsMode for result sets with fewer than 500,000 distinct key arguments to the mapper's emit() function.

booleano

Optional. Specifies whether to include the timing information in the result information. Set verbose to true to include the timing information.

Padrão é false.

This option is ignored. The result information always excludes the timing information. You can view timing information by running explain with the mapReduce command in the "executionStats" or "allPlansExecution" verbosity modes.

booleano

Optional. Enables mapReduce to bypass schema validation during the operation. This lets you insert documents that do not meet the validation requirements.

If the output option is set to inline, no schema validation occurs. If the output goes to a collection, mapReduce observes any validation rules which the collection has and does not insert any invalid documents unless the bypassDocumentValidation parameter is set to true.

documento

Opcional.

Especifica o agrupamento a ser usado para a operação.

A colocação permite que os usuários especifiquem regras específicas do idioma para comparação de strings, como regras para letras maiúsculas e marcas de acento.

A opção de agrupamento tem a seguinte sintaxe:

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

Ao especificar agrupamento, o campo locale é obrigatório; todos os outros campos de agrupamento são opcionais. Para obter descrições dos campos, consulte Documento de agrupamento.

Se o agrupamento não for especificado, mas a coleção tiver um agrupamento padrão (consulte db.createCollection()), a operação usará o agrupamento especificado para a coleção.

Se nenhum agrupamento for especificado para a coleção ou para as operações, o MongoDB usa a comparação binária simples usada nas versões anteriores para comparações de strings.

Você não pode especificar vários agrupamentos para uma operação. Por exemplo, você não pode especificar agrupamentos diferentes por campo ou, se estiver realizando uma busca com uma classificação, não poderá usar um agrupamento para a busca e outro para a classificação.

maxTimeMS

non-negative integer

Opcional.

Especifica um limite de tempo em milissegundos. Se você não especificar um valor para maxTimeMS, as operações não atingirão o tempo limite. Um valor 0 especifica explicitamente o comportamento ilimitado padrão.

O MongoDB encerra as operações que excedem o limite de tempo alocado usando o mesmo mecanismo de db.killOp(). O MongoDB só encerra uma operação em um de seus pontos de interrupção designados.

documento

Optional. A document that expresses the Escreva preocupação to use when outputting to a collection. Omit to use the default write concern.

comment

any

Opcional. Um comentário fornecido pelo usuário para anexar a este comando. Depois de definido, esse comentário aparece junto com os registros desse comando nos seguintes locais:

Um comentário pode ser qualquer tipo BSON válido (string, inteiro, objeto, array etc).

The following is a prototype usage of the mapReduce command:

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

Observação

JavaScript no MongoDB

Although mapReduce uses JavaScript, most interactions with MongoDB do not use JavaScript but use an idiomatic driver in the language of the interacting application.

The map function is responsible for transforming each input document into zero or more documents. It can access the variables defined in the scope parameter, and has the following prototype:

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

The map function has the following requirements:

  • In the map function, reference the current document as this within the function.

  • The map function should não access the database for any reason.

  • The map function should be pure, or have no impact outside of the function (i.e. side effects.)

  • The map function may optionally call emit(key,value) any number of times to create an output document associating key with value.

The following map function will call emit(key,value) either 0 or 1 times depending on the value of the input document's status field:

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

The following map function may call emit(key,value) multiple times depending on the number of elements in the input document's items field:

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

The reduce function has the following prototype:

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

The reduce function exhibits the following behaviors:

  • The reduce function should não access the database, even to perform read operations.

  • The reduce function should não affect the outside system.

  • MongoDB can invoke the reduce function more than once for the same key. In this case, the previous output from the reduce function for that key will become one of the input values to the next reduce function invocation for that key.

  • The reduce function can access the variables defined in the scope parameter.

  • The inputs to reduce must not be larger than half of MongoDB's maximum BSON document size. This requirement may be violated when large documents are returned and then joined together in subsequent reduce steps.

Because it is possible to invoke the reduce function more than once for the same key, the following properties need to be true:

  • the type of the return object must be identical to the type of the value emitted by the map function.

  • the reduce function must be associative. The following statement must be true:

    reduce(key, [ C, reduce(key, [ A, B ]) ] ) == reduce( key, [ C, A, B ] )
  • the reduce function must be idempotent. Ensure that the following statement is true:

    reduce( key, [ reduce(key, valuesArray) ] ) == reduce( key, valuesArray )
  • the reduce function should be commutative: that is, the order of the elements in the valuesArray should not affect the output of the reduce function, so that the following statement is true:

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

The finalize function has the following prototype:

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

The finalize function receives as its arguments a key value and the reducedValue from the reduce function. Be aware that:

  • The finalize function should não access the database for any reason.

  • The finalize function should be pure, or have no impact outside of the function (i.e. side effects.)

  • The finalize function can access the variables defined in the scope parameter.

You can specify the following options for the out parameter:

This option outputs to a new collection, and is not available on secondary members of replica sets.

out: <collectionName>

Observação

Starting in version 4.2, MongoDB deprecates:

  • The map-reduce option to criar a new sharded collection as well as the use of the sharded option for map-reduce. To output to a sharded collection, create the sharded collection first. MongoDB 4.2 also deprecates the replacement of an existing sharded collection.

This option is only available when passing a collection that already exists to out. It is not available on secondary members of replica sets.

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

When you output to a collection with an action, the out has the following parameters:

  • <action>: Specify one of the following actions:

    • replace

      Replace the contents of the <collectionName> if the collection with the <collectionName> exists.

    • merge

      Merge the new result with the existing result if the output collection already exists. If an existing document has the same key as the new result, overwrite that existing document.

    • reduce

      Merge the new result with the existing result if the output collection already exists. If an existing document has the same key as the new result, apply the reduce function to both the new and the existing documents and overwrite the existing document with the result.

  • db:

    Optional. The name of the database that you want the map-reduce operation to write its output. By default this will be the same database as the input collection.

Perform the map-reduce operation in memory and return the result. This option is the only available option for out on secondary members of replica sets.

out: { inline: 1 }

The result must fit within the maximum size of a BSON document.

If your MongoDB deployment enforces authentication, the user executing the mapReduce command must possess the following privilege actions:

Map-reduce with {out : inline} output option:

Map-reduce with the replace action when outputting to a collection:

Map-reduce with the merge or reduce actions when outputting to a collection:

The readWrite built-in role provides the necessary permissions to perform map-reduce aggregation.

O comando mapReduce não mais compatível com afterClusterTime. Então, mapReduce não pode ser associada a sessões causalmente consistentes.

In mongosh, the db.collection.mapReduce() method is a wrapper around the mapReduce command. The following examples use the db.collection.mapReduce() method:

Os exemplos nesta seção incluem alternativas de aggregation pipelines sem expressões de agregação customizadas. Para alternativas que usam expressões personalizadas, consulte Exemplos de tradução do map-reduce para o aggregation pipeline.

Crie uma coleção de amostra orders com estes 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" }
])

Execute a operação map-reduce na collection orders para agrupar pelo cust_id e calcule a soma do price para cada cust_id:

  1. Defina a função do mapa para processar cada documento de entrada:

    • Na função, o this refere-se ao documento que a operação de redução de mapa está processando.

    • A função mapeia o price para o cust_id para cada documento e emite o cust_id e price.

    var mapFunction1 = function() {
    emit(this.cust_id, this.price);
    };
  2. Defina a função de redução correspondente com dois argumentos keyCustId e valuesPrices:

    • O valuesPrices é uma array cujos elementos são os valores price emitidos pela função de mapa e agrupados por keyCustId.

    • A função reduz a array valuesPrice à soma de seus elementos.

    var reduceFunction1 = function(keyCustId, valuesPrices) {
    return Array.sum(valuesPrices);
    };
  3. Executar a redução de mapa em todos os documentos na coleção do orders utilizando a função de mapa do mapFunction1 e a função de redução do reduceFunction1 :

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

    Esta operação gera resultados para uma coleção denominada map_reduce_example. Se a coleção map_reduce_example já existir, a operação substituirá o conteúdo pelos resultados desta operação de redução de mapa.

  4. Consulte a coleção map_reduce_example para verificar os resultados:

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

    A operação retorna estes documentos:

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

Usando os operadores de aggregation pipeline disponíveis, você pode reescrever a operação de map-reduce sem definir funções personalizadas:

db.orders.aggregate([
{ $group: { _id: "$cust_id", value: { $sum: "$price" } } },
{ $out: "agg_alternative_1" }
])
  1. O estágio $group agrupa pelo cust_id e calcula o campo value (consulte também $sum). O campo value contém o total de price para cada cust_id.

    O estágio envia os seguintes documentos para o próximo estágio:

    { "_id" : "Don Quis", "value" : 155 }
    { "_id" : "Ant O. Knee", "value" : 95 }
    { "_id" : "Cam Elot", "value" : 60 }
    { "_id" : "Busby Bee", "value" : 125 }
  2. Em seguida, o $out grava a saída na coleção agg_alternative_1. Alternativamente, você pode utilizar $merge ao invés de $out.

  3. Consulte a coleção agg_alternative_1 para verificar os resultados:

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

    A operação retorna os seguintes documentos:

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

Dica

Veja também:

Para obter uma alternativa que usa expressões de agregação personalizadas, consulte Map-Reduce to Aggregation Pipeline Translation Examples.

No exemplo seguinte, você visualizará uma operação de map-reduce na collection orders para todos os documentos que têm um valor ord_date maior ou igual a 2020-03-01.

A operação no exemplo:

  1. Agrupa pelo campo item.sku e calcula o número de pedidos e a quantidade total solicitada para cada sku.

  2. Calcula a quantidade média por pedido para cada valor sku e mescla os resultados na coleta de saída.

Ao mesclar resultados, se um documento existente tiver a mesma chave que o novo resultado, a operação substituirá o documento existente. Se não houver nenhum documento existente com a mesma chave, a operação inserirá o documento.

Etapas de exemplo:

  1. Defina a função do mapa para processar cada documento de entrada:

    • Na função, o this refere-se ao documento que a operação de redução de mapa está processando.

    • Para cada item, a função associa o sku a um novo objeto value que contém o count de 1 e o item qty para o pedido e emite o sku (armazenado no key) e o 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. Defina a função de redução correspondente com dois argumentos keySKU e countObjVals:

    • countObjVals é um array cujos elementos são os objetos mapeados para os valores agrupados do keySKU passados pela função de mapa para a função de redução.

    • A função reduz a matriz countObjVals para um único objeto reducedValue que contém os campos count e qty.

    • Em reducedVal, o campo count contém a soma dos campos count dos elementos individuais da array e o campo qty contém a soma dos campos qty dos elementos individuais da array.

    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. Defina uma função de finalização com dois argumentos key e reducedVal. A função modifica o objeto reducedVal para adicionar um campo calculado denominado avg e retorna o objeto modificado:

    var finalizeFunction2 = function (key, reducedVal) {
    reducedVal.avg = reducedVal.qty/reducedVal.count;
    return reducedVal;
    };
  4. Execute a operação de redução de mapa na coleção do orders utilizando as funções mapFunction2, reduceFunction2 e finalizeFunction2:

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

    Esta operação utiliza o campo query para selecionar apenas os documentos com ord_date maior ou igual a new Date("2020-03-01"). Em seguida, ele envia os resultados para uma coleção map_reduce_example2.

    Se a coleção map_reduce_example2 já existir, a operação fundirá o conteúdo existente com os resultados desta operação de redução de mapa. Ou seja, se um documento existente tiver a mesma chave que o novo resultado, a operação substituirá o documento existente. Se não houver nenhum documento existente com a mesma chave, a operação inserirá o documento.

  5. Consulte a coleção map_reduce_example2 para verificar os resultados:

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

    A operação retorna estes 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 } }

Usando os operadores de aggregation pipeline disponíveis, você pode reescrever a operação de map-reduce sem definir funções 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. A etapa $match seleciona apenas os documentos com ord_date maior ou igual a new Date("2020-03-01").

  2. O estágio $unwind divide o documento pelo campo de array items para gerar um documento para cada elemento da array. Por exemplo:

    { "_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. Os $group grupos de estágio pelo items.sku, calculando para cada sku:

    • O campo qty. O campo qty contém o
      total qty solicitado por cada items.sku (consulte $sum).
    • A matriz orders_ids. O campo orders_ids contém um
      array de _id de ordem distinta para o items.sku (veja $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 ] }
  4. O estágio $project remodela o documento de saída para espelhar a saída do map-reduce para ter dois campos _id e value. Os conjuntos $project :

  5. O estágio $unwind divide o documento pelo campo de array items para gerar um documento para cada elemento da array. Por exemplo:

    { "_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. Os $group grupos de estágio pelo items.sku, calculando para cada sku:

    • O campo qty. O campo qty contém o total de qty ordenados por cada items.sku utilizando $sum.

    • A array orders_ids. O campo orders_ids contém uma array de ordem distinta _id para o items.sku utilizando $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. O estágio $project remodela o documento de saída para espelhar a saída do map-reduce para ter dois campos _id e value. Os conjuntos $project :

    • o value.count para o tamanho da array orders_ids usando $size.

    • o value.qty para o campo qty do documento de entrada.

    • o value.avg para o número médio de quantidade por pedido usando $divide e $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, o $merge grava a saída na coleção agg_alternative_3. Se um documento existente tiver a mesma chave _id que o novo resultado, a operação substituirá o documento existente. Se não houver nenhum documento existente com a mesma chave, a operação inserirá o documento.

  9. Consulte a coleção agg_alternative_3 para verificar os resultados:

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

    A operação retorna os seguintes 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 } }

Dica

Veja também:

Para obter uma alternativa que usa expressões de agregação personalizadas, consulte Map-Reduce to Aggregation Pipeline Translation Examples.

For more information and examples, see the Map-Reduce page and Executar Redução incremental de mapa

If you set the out parameter to write the results to a collection, the mapReduce command returns a document in the following form:

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

If you set the out parameter to output the results inline, the mapReduce command returns a document in the following form:

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

For output sent to a collection, this value is either:

  • a string for the collection name if out did not specify the database name, or

  • a document with both db and collection fields if out specified both a database and collection name.

mapReduce.results

For output written inline, an array of resulting documents. Each resulting document contains two fields:

  • _id field contains the key value,

  • value field contains the reduced or finalized value for the associated key.

mapReduce.ok

A value of 1 indicates the mapReduce command ran successfully. A value of 0 indicates an error.

In addition to the aforementioned command specific return fields, the db.runCommand() includes additional information:

  • for replica sets: $clusterTime, and operationTime.

  • para clusters fragmentados: operationTime e $clusterTime.

Consulte Resposta db.runCommand para obter detalhes sobre esses campos.