Menu Docs

Página inicial do DocsDesenvolver aplicaçõesManual do MongoDB

db.collection.mapReduce()

Nesta página

  • Sintaxe
  • Saída
  • Restrições
  • Informações adicionais

Observação

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

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

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

db.collection.mapReduce(map,reduce, { <options> })

Importante

Método mongosh

Esta página documenta um método mongosh . Esta não é a documentação para comandos de banco de dados ou drivers específicos de idioma, como Node.js.

Para o comando do banco de dados, consulte o comando mapReduce.

Para drivers de API do MongoDB, consulte a documentação do driver MongoDB específica do idioma.

Para a documentação de shell legada do mongo, consulte a documentação para a versão correspondente do MongoDB Server:

mongo shell v4.4

Observação

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

Observação

O MongoDB ignora a opção detalhada .

A partir da versão 4.2, o MongoDB descontinuará:

  • A opção map-reduce para criar uma nova collection fragmentada, bem como o uso da opção fragmentada para map-reduce. Para gerar saída para uma collection fragmentada, crie primeiro a collection fragmentada. O MongoDB 4.2 também descontinua a substituição de uma collection fragmentada existente.

db.collection.mapReduce() tem a seguinte sintaxe:

db.collection.mapReduce(
<map>,
<reduce>,
{
out: <collection>,
query: <document>,
sort: <document>,
limit: <number>,
finalize: <function>,
scope: <document>,
jsMode: <boolean>,
verbose: <boolean>,
bypassDocumentValidation: <boolean>
}
)

db.collection.mapReduce() recebe os seguintes parâmetros:

Parâmetro
Tipo
Descrição
map
Javascript ou string

Uma função JavaScript que associa ou "mapeia" um value a um key e emite o key e o valor pair. Você pode especificar a função como tipo de BSON JavaScript (tipo de BSON 13) ou String (tipo de BSON 2).

Consulte Requisitos para a função de mapeamento para mais informações.

reduce
Javascript ou string

Uma função JavaScript que "reduz" a um único objeto todos os values associados a uma determinada key. Você pode especificar a função como JavaScript do tipo BSON (BSON tipo 13) ou string (BSON tipo 2).

Consulte Requisitos para a função de redução para mais informações.

options
documento
Um documento que especifica parâmetros adicionais para db.collection.mapReduce().

A tabela seguinte descreve argumentos adicionais que o db.collection.mapReduce() pode aceitar.

Campo
Tipo
Descrição
out
string ou documento

Especifica a localização do resultado da operação de map-reduce. Você pode gerar saída para uma collection, gerar saída para uma collection com uma ação ou gerar saída in-line. Você pode gerar saída para uma collection ao realizar operações de map-reduce nos membros primários do conjunto; em membros secundários, você só pode usar a saída inline.

Consulte Opções para obter mais informações.

query
documento
Especifica os critérios de seleção usando operadores de query para determinar a entrada de documentos para a função map.
sort
documento
Classifica os documentos de entrada. Esta opção é útil para otimização. Por exemplo, especifique que a chave de classificação seja igual à chave de emissão para que haja menos operações de redução. A chave de classificação deve estar em um índice existente para essa collection.
limit
número
Especifica um número máximo de documentos para a entrada na função map.
finalize
Javascript ou string

Opcional. Uma função JavaScript que modifica a saída após a função reduce. Você pode especificar a função como JavaScript do tipo BSON (BSON tipo 13) ou string (BSON tipo 2).

Consulte Requisitos para a função de finalização para mais informações.

scope
documento
Especifica variáveis globais que são acessíveis nas funções map, reduce e finalize.
jsMode
boleano

Especifica se serão convertidos dados intermediários em formato BSON entre a execução das funções map e reduce.

Padrão é false.

Se false:

  • Internamente, o MongoDB converte os objetos JavaScript emitidos pela função map em objetos BSON. Em seguida, esses objetos BSON são convertidos de volta para objetos JavaScript ao chamar a função reduce.

  • A operação map-reduce posiciona os objetos BSON intermediários em armazenamento temporário no disco. Isto permite que a operação map-reduce seja executada em conjuntos de dados arbitrariamente grandes.

Se true:

  • Internamente, os objetos JavaScript emitidos durante a função map permanecem como objetos JavaScript. Não há necessidade de converter os objetos para a função reduce, o que pode resultar em execução mais rápida.

  • Você só pode usar jsMode para conjuntos de resultados com menos de 500.000 argumentos key distintos para a função emit() do mapeador.

verbose
boleano

Especifica se as informações timing devem ser incluídas nas informações do resultado. Defina verbose como true para incluir as informações de timing .

Padrão é false.

A partir do MongoDB 4.4, esta opção é ignorada. As informações do resultado sempre excluem as informações timing . Você pode visualizar as informações de tempo executando db.collection.explain() com db.collection.mapReduce() nos modos "executionStats" ou "allPlansExecution" verbosity .

collation
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 collection 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.

bypassDocumentValidation
boleano
Opcional. Habilita o mapReduce para ignorar a validação do documento durante a operação. Isso permite inserir documentos que não atendam aos requisitos de validação.

Observação

As expressões de operador map-reduce operations e $where não podem acessar determinadas funções ou propriedades globais, como db, que estão disponíveis em mongosh.

As seguintes funções e propriedades do JavaScript estão disponíveis para as expressões de operador map-reduce operations e $where:

Propriedades disponíveis
Funções disponíveis
args
MaxKey
MinKey
assert()
BinData()
DBPointer()
DBRef()
doassert()
emit()
gc()
HexData()
hex_md5()
isNumber()
isObject()
ISODate()
isString()
Map()
MD5()
NumberInt()
NumberLong()
ObjectId()
print()
printjson()
printjsononeline()
sleep()
Timestamp()
tojson()
tojsononeline()
tojsonObject()
UUID()
version()

A função map é responsável por transformar cada documento de entrada em zero ou mais documentos. Ela pode acessar as variáveis definidas no parâmetro scope e tem o seguinte protótipo:

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

A função map tem os seguintes requisitos:

  • Na função map, referencie o documento atual como this dentro da função.

  • A função map não deve acessar o banco de dados por nenhum motivo.

  • A função map deve ser pura ou não impacto fora dela (ou seja, efeitos colaterais).

  • A função map pode, opcionalmente, chamar emit(key,value) várias vezes para criar um documento de saída associando key a value.

A função map a seguir chamará emit(key,value) 0 ou 1 vez, dependendo do valor do campo status do documento de entrada:

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

A função map a seguir pode chamar emit(key,value) várias vezes, dependendo do número de elementos no campo items do documento de entrada:

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

A função reduce tem o seguinte protótipo:

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

A função reduce exibe os seguintes comportamentos:

  • A função reduce não deve acessar o banco de dados, mesmo para realizar operações de leitura.

  • A função reduce não deve afetar o sistema externo.

  • O MongoDB pode invocar a função reduce mais de uma vez para a mesma chave. Neste caso, a saída anterior da função reduce para esta chave se tornará um dos valores de entrada para a próxima invocação da função reduce para esta chave.

  • A função reduce pode acessar as variáveis definidas no parâmetro scope.

  • As entradas para reduce não devem ser maiores que a metade do tamanho máximo do documento BSON do MongoDB. Esse requisito pode ser violado quando documentos grandes são devolvidos e, em seguida, unidos em reduce etapas subsequentes.

Como é possível invocar a função reduce mais de uma vez para a mesma chave, as seguintes propriedades precisam ser verdadeiras:

  • o tipo do objeto de retorno deve ser idêntico ao tipo do value emitido pela função map.

  • a função reduce deve ser associativa. A seguinte declaração deve ser verdadeira:

    reduce(key, [ C, reduce(key, [ A, B ]) ] ) == reduce( key, [ C, A, B ] )
  • a função reduce deve ser idempotente. Confirme se a afirmação a seguir é verdadeira:

    reduce( key, [ reduce(key, valuesArray) ] ) == reduce( key, valuesArray )
  • a função reduce deve ser comutativa, isto é, a ordem dos elementos no valuesArray não deve afetar a saída da função reduce, de forma que a seguinte declaração seja verdadeira:

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

Você pode especificar as seguintes opções para o parâmetro out:

Esta opção gera resultados para uma nova collection e não está disponível para membros secundários de conjuntos de réplicas.

out: <collectionName>

Observação

A partir da versão 4.2, o MongoDB descontinuará:

  • A opção map-reduce para criar uma nova collection fragmentada, bem como o uso da opção fragmentada para map-reduce. Para gerar saída para uma collection fragmentada, crie primeiro a collection fragmentada. O MongoDB 4.2 também descontinua a substituição de uma collection fragmentada existente.

Esta opção só está disponível ao passar uma collection que já existe para out. Não está disponível para membros secundários de conjuntos de réplicas.

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

Quando você gera resultados para uma coleção com uma ação, o out tem os seguintes parâmetros:

  • <action>: especifique uma das seguintes ações:

    • replace

      Substitua o conteúdo de <collectionName> se a collection com <collectionName> existir.

    • merge

      Mescle o novo resultado com o resultado existente se a collection de saída já existir. Se um documento existente tiver a mesma chave que o novo resultado, substitua esse documento existente.

    • reduce

      Mescle o novo resultado com o resultado existente se a collection de saída já existir. Se um documento existente tiver a mesma chave que o novo resultado, aplique a função reduce aos documentos novo e existente e substitua o documento existente pelo resultado.

  • db:

    Opcional. O nome do banco de dados em que você deseja que a operação map-reduce escreva sua saída. Por padrão, este será o mesmo banco de dados que a collection de entrada.

  • sharded:

    Observação

    A partir da versão 4.2, o uso da opção sharded foi descontinuado.

    Opcional. Se true e você tiver ativado a fragmentação no banco de dados de saída, a operação map-reduce fragmentará a collection de saída usando o campo _id como chave de shard.

    Se true e collectionName for uma collection não fragmentada existente, map-reduce falhará.

Execute a operação map-reduce na memória e retorne o resultado. Esta opção é a única disponível para out em membros secundários de conjuntos de réplicas.

out: { inline: 1 }

O resultado deve caber no tamanho máximo de um documento BSON.

A função finalize tem o seguinte protótipo:

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

A função finalize recebe como seus argumentos um valor key e reducedValue da função reduce. Esteja ciente de que:

  • A função finalize não deve acessar o banco de dados por nenhum motivo.

  • A função finalize deve ser pura ou não impacto fora dela (ou seja, efeitos colaterais).

  • A função finalize pode acessar as variáveis definidas no parâmetro scope.

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 é uma matriz cujos elementos são os objetos mapeados para os valores agrupados do keySKU passados pela função de mapa para a função redutor.

    • 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.

A saída do método db.collection.mapReduce() é idêntica à do comando mapReduce . Consulte a seção Saída do comando mapReduce para obter informações sobre a saída db.collection.mapReduce() .

Os drivers do MongoDB definem automaticamente o afterClusterTime para operações associadas a sessões normalmente consistentes. Iniciando no MongoDB 4.2, o db.collection.mapReduce() não suporta mais afterClusterTime. Como tal, db.collection.mapReduce() não pode ser associada a sessões causalmente consistentes.

← db.collection.latencyStats()