db.collection.mapReduce()
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 redução de mapa utilizando estágios do pipeline de agregação, 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:
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 nem drivers específicos de linguagem, 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 do MongoDB específica da linguagem.
Observação
As visualizações não suportam operações de redução de mapa.
Compatibilidade
Esse método 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
Sintaxe
Observação
O MongoDB ignora a opção detalhamento.
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 |
---|---|---|
| Javascript ou string | Uma função JavaScript que associa ou "mapeia" um Consulte Requisitos para a função de mapeamento para mais informações. |
| Javascript ou string | Uma função JavaScript que "reduz" a um único objeto todos os Consulte Requisitos para a função de redução para mais informações. |
| documento | Um documento que especifica parâmetros adicionais para |
A tabela a seguir descreve argumentos adicionais que o db.collection.mapReduce()
pode aceitar.
Campo | Tipo | Descrição | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
| 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 Consulte Opções para obter mais informações. | ||||||||||
| documento | Especifica os critérios de seleção usando operadores de query para determinar a entrada de documentos para a função | ||||||||||
| 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. | ||||||||||
| número | Especifica um número máximo de documentos para a entrada na função | ||||||||||
| Javascript ou string | Opcional. Uma função JavaScript que modifica a saída após a função Consulte Requisitos para a função de finalização para mais informações. | ||||||||||
| documento | Especifica variáveis globais que são acessíveis nas funções | ||||||||||
| booleano | Especifica se serão convertidos dados intermediários em formato BSON entre a execução das funções Padrão é Se
Se
| ||||||||||
| booleano | Especifica se as informações Padrão é Esta opção é ignorada. As informações do resultado sempre excluem as informações de | ||||||||||
| 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:
Ao especificar agrupamento, o campo Se o agrupamento não for especificado, mas a coleção tiver um agrupamento padrão (consulte 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. Novidade na versão 3.4. | ||||||||||
| booleano | Opcional. Habilita o Novo na versão 3.2. |
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() |
Requisitos para a map
função
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 comothis
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, chamaremit(key,value)
várias vezes para criar um documento de saída associandokey
avalue
.
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); }); }
Requisitos para a reduce
função
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çãoreduce
para esta chave se tornará um dos valores de entrada para a próxima invocação da funçãoreduce
para esta chave.A função
reduce
pode acessar as variáveis definidas no parâmetroscope
.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 emreduce
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çãomap
.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 novaluesArray
não deve afetar a saída da funçãoreduce
, de forma que a seguinte declaração seja verdadeira:reduce( key, [ A, B ] ) == reduce( key, [ B, A ] )
out
Opções
Você pode especificar as seguintes opções para o parâmetro out
:
Saída para uma collection
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>
Saída para uma collection com uma ação
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.
Gerar saída in-line
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.
Requisitos para a finalize
função
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âmetroscope
.
Exemplos de map-reduce
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" } ])
Retornar o preço total por cliente
Execute a operação map-reduce na collection orders
para agrupar pelo cust_id
e calcule a soma do price
para cada cust_id
:
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 ocust_id
para cada documento e emite ocust_id
eprice
.
var mapFunction1 = function() { emit(this.cust_id, this.price); }; Defina a função de redução correspondente com dois argumentos
keyCustId
evaluesPrices
:O
valuesPrices
é uma array cujos elementos são os valoresprice
emitidos pela função de mapa e agrupados porkeyCustId
.A função reduz a array
valuesPrice
à soma de seus elementos.
var reduceFunction1 = function(keyCustId, valuesPrices) { return Array.sum(valuesPrices); }; Executar a redução de mapa em todos os documentos na coleção do
orders
utilizando a função de mapa domapFunction1
e a função de redução doreduceFunction1
: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çãomap_reduce_example
já existir, a operação substituirá o conteúdo pelos resultados desta operação de redução de mapa.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 }
Alternativa de aggregation
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" } ])
O estágio
$group
agrupa pelocust_id
e calcula o campovalue
(consulte também$sum
). O campovalue
contém o total deprice
para cadacust_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 } Em seguida, o
$out
grava a saída na coleçãoagg_alternative_1
. Alternativamente, você pode utilizar$merge
ao invés de$out
.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.
Calcule o pedido e a quantidade total com a quantidade média por item
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:
Agrupa pelo campo
item.sku
e calcula o número de pedidos e a quantidade total solicitada para cadasku
.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:
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 objetovalue
que contém ocount
de1
e o itemqty
para o pedido e emite osku
(armazenado nokey
) e ovalue
.
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); } }; Defina a função de redução correspondente com dois argumentos
keySKU
ecountObjVals
:countObjVals
é uma matriz cujos elementos são os objetos mapeados para os valores agrupados dokeySKU
passados pela função de mapa para a função redutor.A função reduz a matriz
countObjVals
para um único objetoreducedValue
que contém os camposcount
eqty
.Em
reducedVal
, o campocount
contém a soma dos camposcount
dos elementos individuais da array e o campoqty
contém a soma dos camposqty
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; }; Defina uma função de finalização com dois argumentos
key
ereducedVal
. A função modifica o objetoreducedVal
para adicionar um campo calculado denominadoavg
e retorna o objeto modificado:var finalizeFunction2 = function (key, reducedVal) { reducedVal.avg = reducedVal.qty/reducedVal.count; return reducedVal; }; Execute a operação de redução de mapa na coleção do
orders
utilizando as funçõesmapFunction2
,reduceFunction2
efinalizeFunction2
: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 comord_date
maior ou igual anew Date("2020-03-01")
. Em seguida, ele envia os resultados para uma coleçãomap_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.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 } }
Alternativa de aggregation
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" } } ] )
A etapa
$match
seleciona apenas os documentos comord_date
maior ou igual anew Date("2020-03-01")
.O estágio
$unwind
divide o documento pelo campo de arrayitems
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" } ... Os
$group
grupos de estágio peloitems.sku
, calculando para cada sku:- O campo
qty
. O campoqty
contém o - total
qty
solicitado por cadaitems.sku
(consulte$sum
).
- O campo
- A matriz
orders_ids
. O campoorders_ids
contém um - array de
_id
de ordem distinta para oitems.sku
(veja$addToSet
).
- A matriz
{ "_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 ] } O estágio
$project
remodela o documento de saída para espelhar a saída do map-reduce para ter dois campos_id
evalue
. Os conjuntos$project
:O estágio
$unwind
divide o documento pelo campo de arrayitems
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" } ... Os
$group
grupos de estágio peloitems.sku
, calculando para cada sku:O campo
qty
. O campoqty
contém o total deqty
ordenados por cadaitems.sku
utilizando$sum
.A array
orders_ids
. O campoorders_ids
contém uma array de ordem distinta_id
para oitems.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 ] } O estágio
$project
remodela o documento de saída para espelhar a saída do map-reduce para ter dois campos_id
evalue
. Os conjuntos$project
:o
value.count
para o tamanho da arrayorders_ids
usando$size
.o
value.qty
para o campoqty
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 } } Finalmente, o
$merge
grava a saída na coleçãoagg_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.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.
Saída
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()
.
Restrições
db.collection.mapReduce()
não oferece mais suporte a afterClusterTime. Como tal, db.collection.mapReduce()
não pode ser associada a sessões causalmente consistentes.