Alguns operadores de agregação , como $avg, $sum e $max, aparecem em mais de um contexto, e cada contexto dá ao operador um comportamento diferente. Por exemplo:
Como expressão,
$avgretorna a média dos elementos em uma array.Como acumulador,
$avgretorna a média de valores em um grupo de documentos.Como função de janela,
$avgretorna a média dos valores dos documentos em uma janela.
O estágio que contém um operador determina seu comportamento. O mesmo nome de operador pode aceitar argumentos diferentes e retornar resultados diferentes dependendo de onde você o usa. Esta página descreve os três contextos e como desambigua-los.
O diagrama a seguir conceitualiza como as expressões, acumuladores e funções de janela são executadas:
A tabela a seguir resume como os três tipos de operador diferem.
Tipo de operador | Comportamento | Onde você pode usá-lo |
|---|---|---|
Expressão | Avaliado em cada documento de entrada e retorna um valor por documento. |
|
acumulador | Agrega em um grupo de documentos de entrada e retorna um valor agregado por grupo. | |
Função de janela | Avaliado em uma janela de documentos de entrada e retorna um valor por documento. |
|
Expressões
Uma expressão se torna um valor para um único documento de entrada. As expressões não alteram suas entradas.
Os operadores de expressão aceitam uma array de argumentos e têm a seguinte forma genérica:
{ <operator>: [ <argument1>, <argument2> ... ] }Se um operador aceitar um único argumento, você poderá omitir a array externa.
As expressões também fornecem os argumentos para acumuladores e funções de janela. Por exemplo, em { $sum: "$price" }, o caminho do campo "$price" é uma expressão.
Para saber mais,consulte Expressões.
Accumulators
Um acumulador calcula um único valor agregado, como uma soma, máximo ou mínimo, em um número variável de documentos de entrada. Em implementações práticas, os acumuladores mantêm o estado entre os documentos que processam durante a execução de uma operação de agrupamento.
O número de documentos de saída retornados por um estágio $group é igual ao número de grupos. Para cada um desses grupos, um acumulador calcula um valor agregado no grupo.
Você pode usar acumuladores nos estágios do pipeline de agregação que executam operações de agrupamento:
Para saber mais,consulte Acumuladores.
Funções de janela
Uma função de janela retorna um valor baseado em uma janela, que é uma extensão de documentos definidos em relação ao documento atual. Você define a janela com os campos partitionBy, sortBy e window do estágio$setWindowFields.
Para operadores que trabalham como acumuladores e funções de janela, a diferença é o que o operador agrega e quantos valores ele retorna:
Como acumulador, o operador agrega um grupo de documentos e retorna um único valor para o grupo.
Como função de janela, o operador agrega em uma janela de documentos e retorna um valor para cada documento.
Você pode utilizar funções de janela somente no estágio $setWindowFields. $setWindowFields também oferece suporte a operadores específicos do Windows, como $rank e $shift.
Para saber mais, consulte Funções da janela.
Exemplo
Os exemplos nesta página usam dados do conjunto de dados sample_mflix. Para obter detalhes sobre como carregar este conjunto de dados em sua implantação do MongoDB autogerenciado, consulte Carregar o conjunto de dados de amostra. Se você fez alguma modificação nos bancos de dados de amostra, talvez seja necessário descartar e recriar os bancos de dados para executar os exemplos nesta página.
Os exemplos a seguir usam $sum em todos os três contextos. Cada um retorna um resultado diferente, que mostra como o contexto determina o comportamento de um operador.
Exemplo de expressão
O exemplo a seguir usa $sum como uma expressão para adicionar dois campos dentro de cada documento. O pipeline retorna um total para cada documento correspondente.
db.movies.aggregate( [ { $match: { title: { $in: [ "The Godfather", "Inception", "The Dark Knight" ] } } }, { $project: { _id: 0, title: 1, totalAwards: { $sum: [ "$awards.wins", "$awards.nominations" ] } } }, { $sort: { totalAwards: -1 } }] )Exemplo de acumulador
O exemplo a seguir usa $sum como acumulador para totalizar um campo em cada documento em cada grupo. O pipeline retorna um total para cada classificação de conteúdo , em vez de um total para cada documento.
db.movies.aggregate( [ { $match: { rated: { $in: [ "G", "PG", "PG-13", "R" ] }, "imdb.votes": { $type: "int" } } }, { $group: { _id: "$rated", totalVotes: { $sum: "$imdb.votes" } } }, { $sort: { _id: 1 } }] )Exemplo de função de janela
O exemplo a seguir usa $sum como uma função de janela para totalizar um campo em uma janela de documentos. O pipeline retorna um total em execução para cada documento, e esse total depende da janela do documento.
db.movies.aggregate( [ { $match: { genres: "Musical", year: { $in: [ 2009, 2010 ] }, "imdb.rating": { $type: "double" }, "imdb.votes": { $gt: 0 } } }, { $setWindowFields: { partitionBy: "$year", sortBy: { title: 1 }, output: { cumulativeVotesInYear: { $sum: "$imdb.votes", window: { documents: [ "unbounded", "current" ] } }, rankInYear: { $documentNumber: {} } } } }, { $project: { _id: 0, title: 1, year: 1, "imdb.votes": 1, cumulativeVotesInYear: 1, rankInYear: 1 } }, { $sort: { year: 1, title: 1 } }] )