Alguns operadores de agregação, como $avg, $sum e $max, aparecem em mais de um contexto, e cada contexto confere ao operador um comportamento diferente. Por exemplo:
Como uma expressão,
$avgretorna a média dos elementos em um array.Como um acumulador,
$avgretorna a média de valores em um grupo de documento.Como uma função de janela,
$avgretorna a média de valores dos documentos em uma janela.
O estágio que contém um operador determina seu comportamento. O mesmo nome de operador pode aceitar diferentes argumentos e retornar diferentes resultados, dependendo de onde você o utiliza. Esta página descreve os três contextos e como diferenciá-los.
O diagrama a seguir conceitua como expressões, acumuladores e funções de janela são executados:
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 é resolvida em um valor para um único documento de entrada. As expressões não alteram suas entradas.
Os operadores de expressão aceitam um array de argumentos e têm a seguinte forma genérica:
{ <operator>: [ <argument1>, <argument2> ... ] }Se um operador aceita um único argumento, você pode 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ão.
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 enquanto executam 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 em todo o grupo.
Você pode usar acumuladores nas fases do pipeline de agregação que realizam operações de agrupamento:
Para aprender mais, consulte Acumuladores.
Funções de janela
Uma função de janela retorna um valor baseado em uma janela, que é um intervalo de documento definido em relação ao documento atual. Você define a janela com os campo partitionBy, sortBy e window do estágio $setWindowFields.
Para operadores que funcionam tanto como acumuladores quanto como funções de janela, a diferença está no que o operador agrega e em quantos valores ele retorna:
Como um acumulador, o operador agrega um grupo de documento e retorna um único valor para o grupo.
Como uma função de janela, o operador agrega em uma janela de documento e retorna um valor para cada documento.
Você pode usar funções de janela apenas no estágio $setWindowFields. $setWindowFields também oferece suporte a operadores específicos para Windows, como $rank e $shift.
Para aprender mais, consulte Funções de 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, o 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 que ele corresponde.
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 um acumulador para totalizar um campo em cada documento de 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 acumulado 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 } }] )