Algunos operadores de agregación, como $avg, $sum y $max, aparecen en más de un contexto, y cada contexto le da al operador un comportamiento diferente. Por ejemplo:
Como expresión,
$avgdevuelve el promedio de los elementos en un arreglo.Como acumulador,
$avgdevuelve el promedio de los valores en un grupo de documento.Como función de ventana,
$avgdevuelve el promedio de los valores de los documentos en una ventana.
La etapa que contiene un operador determina su comportamiento. El mismo nombre de operador puede aceptar diferentes argumentos y devolver diferentes resultados según dónde lo utilice. Esta página describe los tres contextos y cómo desambiguarlos.
El siguiente diagrama conceptualiza cómo se ejecutan las expresiones, los acumuladores y las funciones de ventana:
La siguiente tabla resume las diferencias entre los tres tipos de operador.
Tipo de operador | Comportamiento | Dónde se puede utilizar |
|---|---|---|
expresión | Se evalúa sobre cada documento de entrada y devuelve un valor por documento. |
|
acumulador | Realiza agregaciones sobre un grupo de documentos de entrada y devuelve un valor agregado por grupo. | |
Función de ventana | Evaluado sobre una ventana de documentos de entrada y devuelve un valor por documento. |
|
Expresiones
Una expresión se resuelve en un valor para un solo documento de entrada. Las expresiones no mutan sus entradas.
Los operador de expresión aceptan un arreglo de argumentos y tienen la siguiente forma genérica:
{ <operator>: [ <argument1>, <argument2> ... ] }Si un operador acepta un solo argumento, puede omitir el arreglo externo.
Las expresiones también proporcionan los argumentos para los acumuladores y las funciones de ventana. Por ejemplo, en { $sum: "$price" }, la ruta de campo "$price" es una expresión.
Para aprender más, consulte Expresiones.
Acumuladores
Un acumulador calcula un único valor agregado, como una suma, un máximo o un mínimo, a través de un número variable de documentos de entrada. En las implementaciones prácticas, los acumuladores mantienen el estado entre los documentos que procesan mientras ejecutan una operación de agrupación.
El número de documento de salida devueltos por una etapa $group es igual al número de grupos. Para cada uno de estos grupos, un acumulador calcula un valor agregado en todo el grupo.
Puede usar acumuladores en las etapas del pipeline de agregación que realizan operaciones de agrupación:
Para obtener más información, consulta Acumulador.
Funciones de ventana
Una función de ventana devuelve un valor basado en una ventana, que es un intervalo de documento definido en relación con el documento actual. Define la ventana con los campo partitionBy, sortBy y window de la etapa $setWindowFields.
Para los operadores que funcionan tanto como acumuladores como funciones de ventana, la diferencia radica en qué agrega el operador y cuántos valores devuelve:
Como acumulador, el operador agrega sobre un grupo de documentos y devuelve un valor único para el grupo.
Como función de ventana, el operador agrega sobre una ventana de documentos y devuelve un valor para cada documento.
Solo puede usar funciones de ventana en la etapa $setWindowFields. $setWindowFields también admite operadores específicos de ventanas, como $rank y $shift.
Para aprender más, consultar Funciones de ventana.
Ejemplo
Los ejemplos de esta página utilizan datos del conjunto de datos sample_mflix. Para obtener más información sobre cómo cargar este conjunto de datos en la implementación autogestionada de MongoDB, consultar Cargar el conjunto de datos de muestra. Si realizó alguna modificación en las bases de datos de muestra, es posible que deba descartar y volver a crear las bases de datos para ejecutar los ejemplos de esta página.
Los siguientes ejemplo utilizan $sum en los tres contextos. Cada uno devuelve un resultado diferente, lo que muestra cómo el contexto determina el comportamiento de un operador.
Ejemplo de expresión
El siguiente ejemplo utiliza $sum como expresión para sumar dos campos dentro de cada documento. El pipeline devuelve un total para cada documento que coincide.
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 } }] )Ejemplo de acumulador
El siguiente ejemplo utiliza $sum como acumulador para sumar un campo en cada documento de cada grupo. El pipeline devuelve un total para cada clasificación de contenido en lugar de un 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 } }] )Ejemplo de función de ventana
El siguiente ejemplo utiliza $sum como función de ventana para totalizar un campo en una ventana de documentos. El pipeline devuelve un total acumulado para cada documento, y ese total depende de la ventana del 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 } }] )