Agregação
Definição
aggregate
Executa operação de agregação utilizando o pipeline de agregação. O pipeline permite que os usuários processem dados de uma coleção ou de outra fonte com uma sequência de manipulações baseadas em estágios.
Dica
Em
mongosh
, este comando também pode ser executado por meio dos métodos auxiliaresdb.aggregate()
edb.collection.aggregate()
ou com o método auxiliarwatch()
.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.
Compatibilidade
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 tem suporte limitado 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
Alterado na versão 5.0.
O comando tem a seguinte sintaxe:
db.runCommand( { aggregate: "<collection>" || 1, pipeline: [ <stage>, <...> ], explain: <boolean>, allowDiskUse: <boolean>, cursor: <document>, maxTimeMS: <int>, bypassDocumentValidation: <boolean>, readConcern: <document>, collation: <document>, hint: <string or document>, comment: <any>, writeConcern: <document>, let: <document> // Added in MongoDB 5.0 } )
Campos de comando
O comando aggregate
usa os seguintes campos como argumentos:
Campo | Tipo | Descrição | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
aggregate | string | O nome da collection ou visualização que atua como entrada para o aggregation pipeline. Use 1 para comandos independentes de collection. | ||||||||||
pipeline | array | Uma array de estágios aggregation pipeline que processam e transformam o fluxo de documentos como parte do aggregation pipeline. | ||||||||||
explain | booleano | Opcional. Especifica para devolver as informações sobre o processamento do pipeline. Não disponível em transações com vários documentos. | ||||||||||
| booleano | Opcional. Utilize esta opção para substituir o
A partir do MongoDB 6.0, se Para detalhes, consulte As mensagens de registro do criador de perfil e as mensagens de registro de diagnóstico incluem um indicador | ||||||||||
cursor | documento | Especifique um documento que contenha opções que controlem a criação do objeto cursor. O MongoDB remove o uso do comando
| ||||||||||
maxTimeMS | non-negative integer | Opcional. Especifica um limite de tempo em milissegundos. Se você não especificar um valor para O MongoDB encerra as operações que excedem o limite de tempo alocado usando o mesmo mecanismo de | ||||||||||
bypassDocumentValidation | booleano | |||||||||||
readConcern | documento | Opcional. Especifica a read concern. A opção Os possíveis níveis de read concern são:
Para obter mais informações sobre os read concern, consulte Níveis de read concern. O estágio O estágio | ||||||||||
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:
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. | ||||||||||
hint | string ou documento | Opcional. O índice a ser usado para a aggregation. O índice está na collection/visualização inicial em relação à qual a aggregation é executada. Especifique o índice pelo nome do índice ou pelo documento de especificação do índice. O | ||||||||||
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). Qualquer comentário definido em um comando | ||||||||||
writeConcern | documento | Opcional. Um documento que expressa a write concern a ser usado com o estágio
| ||||||||||
let | documento | Opcional. Especifica um documento com uma lista de variáveis. Isso permite que você melhore a legibilidade do comando separando as variáveis do texto da query. A sintaxe do documento é:
A variável é definida para o valor retornado pela expressão e não pode ser alterada posteriormente. Para acessar o valor de uma variável no comando, use o prefixo de dois cifrões ( Para usar uma variável para filtrar resultados em um estágio Para um exemplo completo utilizando Novidades na versão 5.0. |
O MongoDB remove o uso do comando aggregate
sem a opção cursor
a menos que o comando inclua a opção explain
. A menos que você inclua a opção explain
, especifique a opção cursor.
Para indicar um cursor com o tamanho de lote padrão, especifique
cursor: {}
.Para indicar um cursor com um tamanho de lote não padrão, use
cursor: { batchSize: <num> }
.
Para obter mais informações sobre o pipeline de agregação, consulte:
Sessões
Para cursores criados dentro de uma sessão, você não pode chamar getMore
fora da sessão.
Da mesma forma, para cursores criados fora de uma sessão, você não pode chamar getMore
dentro de uma sessão.
Tempo-limite de inatividade da sessão
Os drivers MongoDB e mongosh
associam todas as operações a uma sessão do servidor, com exceção das operações de gravação não reconhecidas. No caso das operações não associadas explicitamente a uma sessão (ou seja, usando Mongo.startSession()
), os drivers MongoDB e mongosh
criam uma sessão implícita e a associam à operação.
Se uma sessão estiver ociosa por mais de 30 minutos, o servidor MongoDB marcará essa sessão como expirada e poderá fechá-la a qualquer momento. Quando o servidor MongoDB fecha a sessão, ele também elimina todas as operações em andamento e abre os cursores associados à sessão. Isso inclui cursores configurados com noCursorTimeout()
ou maxTimeMS()
com mais de 30 minutos.
Para operações que retornam um cursor, se o cursor puder ficar ocioso por mais de 30 minutos, emita a operação em uma sessão explícita usando Mongo.startSession()
e atualize periodicamente a sessão usando o comando refreshSessions
. Consulte Tempo limite de inatividade da sessão para obter mais informações.
Transações
aggregate
pode ser usado dentro de transações distribuídas.
No entanto, os seguintes estágios não são permitidos nas transações:
Você também não pode especificar a opção explain
.
Para cursores criados fora de uma transação, você não pode chamar
getMore
dentro da transação.Para cursores criados em uma transação, não é possível chamar
getMore
fora da transação.
Importante
Na maioria dos casos, uma transação distribuída incorre em um custo de desempenho maior do que as gravações de um único documento, e a disponibilidade de transações distribuídas não deve substituir o design eficaz do esquema. Em muitos cenários, o modelo de dados desnormalizado (documentos e arrays incorporados) continuará a ser ideal para seus dados e casos de uso. Ou seja, para muitos cenários, modelar seus dados adequadamente minimizará a necessidade de transações distribuídas.
Para considerações adicionais sobre o uso de transações (como limite de tempo de execução e limite de tamanho do oplog), consulte também Considerações de produção.
Desconexão do cliente
Para aggregate
a operação que não inclua os estágios $out
ou $merge
:
A partir do MongoDB 4.2, se o cliente que emitiu aggregate
se desconectar antes da conclusão da operação, o MongoDB marcará aggregate
para encerramento usando killOp
.
Stable API
Ao usar a API estável V1:
Você não pode utilizar as seguintes etapas em um comando
aggregate
:Não inclua o campo
explain
em um comandoaggregate
. Se fizer isso, o servidor retornará um erro APIStrictError .Ao usar o estágio
$collStats
, você só pode usar o campocount
. Nenhum outro campo$collStats
está disponível.
Exemplo
O MongoDB remove o uso do comando aggregate
sem a opção cursor
a menos que o comando inclua a opção explain
. A menos que você inclua a opção explain
, especifique a opção cursor.
Para indicar um cursor com o tamanho de lote padrão, especifique
cursor: {}
.Para indicar um cursor com um tamanho de lote não padrão, use
cursor: { batchSize: <num> }
.
Em vez de executar o comando aggregate
diretamente, a maioria dos usuários deve usar o auxiliar db.collection.aggregate()
fornecido no mongosh
ou o auxiliar equivalente no seu driver. Na versão 2.6 e posteriores, o auxiliar db.collection.aggregate()
sempre retorna um cursor.
Exceto para os dois primeiros exemplos que demonstram a sintaxe de comando, os exemplos nesta página utilizam o auxiliar db.collection.aggregate()
.
Agregar Dados com Pipeline Multi-Estágio
Uma collection articles
contém documentos como os seguintes:
{ _id: ObjectId("52769ea0f3dc6ead47c9a1b2"), author: "abc123", title: "zzz", tags: [ "programming", "database", "mongodb" ] }
O exemplo a seguir executa uma operação aggregate
na coleção articles
para calcular a contagem de cada elemento distinto na array tags
que aparece na coleção.
db.runCommand( { aggregate: "articles", pipeline: [ { $project: { tags: 1 } }, { $unwind: "$tags" }, { $group: { _id: "$tags", count: { $sum : 1 } } } ], cursor: { } } )
Em mongosh
, essa operação pode usar o auxiliar db.collection.aggregate()
, como a seguir:
db.articles.aggregate( [ { $project: { tags: 1 } }, { $unwind: "$tags" }, { $group: { _id: "$tags", count: { $sum : 1 } } } ] )
Use $currentOp em um Banco de Dados Administrativo
O exemplo a seguir executa um pipeline com dois estágios no banco de dados admin. O primeiro estágio executa a operação$currentOp
e o segundo estágio filtra os resultados dessa operação.
db.adminCommand( { aggregate : 1, pipeline : [ { $currentOp : { allUsers : true, idleConnections : true } }, { $match : { shard : "shard01" } } ], cursor : { } } )
Observação
O comando aggregate
não especifica uma coleção. Em vez disso, assume o formato {aggregate: 1}
. Isso ocorre porque o estágio inicial $currentOp
não extrai entrada de uma coleção. Ele produz seus próprios dados que o resto do pipeline usa.
O novo auxiliar dedb.aggregate()
foi adicionado para ajudar na execução de aggregations sem collection como esta. A aggregation acima também pode ser executada como este exemplo.
Informações de Retorno sobre a Operação de Agregação
A seguinte operação de aggregation define o campo opcional explain
para true
para retornar informações sobre a operação de aggregation.
db.orders.aggregate([ { $match: { status: "A" } }, { $group: { _id: "$cust_id", total: { $sum: "$amount" } } }, { $sort: { total: -1 } } ], { explain: true } )
Observação
A saída de explicação está sujeita a alterações entre as versões.
Interação com allowDiskUseByDefault
A partir do MongoDB 6.0, os estágios do pipeline que exigem mais de 100 megabytes de memória para execução gravam arquivos temporários no disco por padrão. Esses arquivos temporários duram durante a execução do pipeline e podem influenciar o espaço de armazenamento na sua instância. Em versões anteriores do MongoDB, você deve passar { allowDiskUse: true }
para find
individuais e comandos aggregate
para habilitar esse comportamento.
Somente find
e aggregate
comandos podem substituir o parâmetro allowDiskUseByDefault
por um ou outro:
Usando
{ allowDiskUse: true }
para permitir a gravação de arquivos temporários no disco quandoallowDiskUseByDefault
estiver definido comofalse
Usando
{ allowDiskUse: false }
para proibir a gravação de arquivos temporários no disco quandoallowDiskUseByDefault
estiver definido comotrue
As mensagens de registro do criador de perfil e as mensagens de registro de diagnóstico incluem um indicador usedDisk
se algum estágio de agregação gravou dados em arquivos temporários devido a restrições de memória.
Dados Agregados Especificando o Tamanho do Lote
Para especificar um tamanho de lote inicial, especifique o batchSize
no campo cursor
, como no seguinte exemplo:
db.orders.aggregate( [ { $match: { status: "A" } }, { $group: { _id: "$cust_id", total: { $sum: "$amount" } } }, { $sort: { total: -1 } }, { $limit: 2 } ], { cursor: { batchSize: 0 } } )
O documento do { cursor: { batchSize: 0 } }
, que especifica o tamanho do tamanho do lote inicial, indica um primeiro lote vazio. Esse tamanho de lote é útil para retornar rapidamente um cursor ou uma mensagem de falha sem realizar um trabalho significativo no lado do servidor.
Para especificar o tamanho do lote para operações subsequentes do getMore
(após o lote inicial), utilize o campo batchSize
ao executar o comando getMore
.
Especificar um agrupamento
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.
Uma coleção myColl
possui os seguintes documentos:
{ _id: 1, category: "café", status: "A" } { _id: 2, category: "cafe", status: "a" } { _id: 3, category: "cafE", status: "a" }
A seguinte operação de aggregation inclui a opção Agrupamento:
db.myColl.aggregate( [ { $match: { status: "A" } }, { $group: { _id: "$category", count: { $sum: 1 } } } ], { collation: { locale: "fr", strength: 1 } } );
Para obter descrições sobre os campos de agrupamento, consulte Documento de agrupamento.
Sugerir um Índice
Crie uma collection foodColl
com os seguintes documentos:
db.foodColl.insertMany( [ { _id: 1, category: "cake", type: "chocolate", qty: 10 }, { _id: 2, category: "cake", type: "ice cream", qty: 25 }, { _id: 3, category: "pie", type: "boston cream", qty: 20 }, { _id: 4, category: "pie", type: "blueberry", qty: 15 } ] )
Crie os seguintes índices:
db.foodColl.createIndex( { qty: 1, type: 1 } ); db.foodColl.createIndex( { qty: 1, category: 1 } );
A seguinte operação de aggregation inclui a opção hint
para forçar o uso do índice especificado:
db.foodColl.aggregate( [ { $sort: { qty: 1 }}, { $match: { category: "cake", qty: 10 } }, { $sort: { type: -1 } } ], { hint: { qty: 1, category: 1 } } )
Substituir o Padrão Atenção com a Leitura
Para substituir o nível de preocupação de leitura padrão, utilize a opção readConcern
. O comando getMore
usa o nível readConcern
especificado no comando aggregate
de origem.
Não é possível usar o stage $out
ou $merge
em conjunto com a read concern "linearizable"
. Ou seja, se você especificar "linearizable"
read concern para db.collection.aggregate()
, não poderá incluir nenhum dos estágios no pipeline.
A operação a seguir em um conjunto de réplicas especifica uma read concern de "majority"
para ler a cópia mais recente dos dados confirmados como tendo sido gravados na maioria dos nós.
Importante
Você pode especificar o nível de preocupação de leitura
"majority"
para uma agregação que inclui um estágio$out
.Independentemente do nível de read concern, os dados mais recentes em um nó podem não refletir a versão mais recente dos dados no sistema.
db.restaurants.aggregate( [ { $match: { rating: { $lt: 5 } } } ], { readConcern: { level: "majority" } } )
Para garantir que um único thread possa ler suas próprias gravações, use "majority"
read concern e "majority"
write concern em relação ao primário do conjunto de réplicas.
Usar variáveis em let
Novidades na versão 5.0.
Para definir variáveis que você pode acessar em outro lugar no comando, use a opção let .
Observação
Crie uma collection cakeSales
contendo vendas para sabores de bolo:
db.cakeSales.insertMany( [ { _id: 1, flavor: "chocolate", salesTotal: 1580 }, { _id: 2, flavor: "strawberry", salesTotal: 4350 }, { _id: 3, flavor: "cherry", salesTotal: 2150 } ] )
O seguinte exemplo:
recupera o bolo que tem um
salesTotal
maior que 3000, que é o bolo com um_id
de 2define uma variável
targetTotal
emlet
, que é referenciada em$gt
como$$targetTotal
db.runCommand( { aggregate: db.cakeSales.getName(), pipeline: [ { $match: { $expr: { $gt: [ "$salesTotal", "$$targetTotal" ] } } }, ], cursor: {}, let: { targetTotal: 3000 } } )