Algunos operadores de agregación, como $avg, $sum y $max, aparecen en más de un contexto, y cada contexto le confiere al operador un comportamiento diferente. Por ejemplo:
Como expresión,
$avgdevuelve el promedio de los elementos de una matriz.Como acumulador,
$avgdevuelve el promedio de los valores de un grupo de documentos.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. Un mismo nombre de operador puede aceptar diferentes argumentos y devolver resultados distintos según el contexto en el que se utilice. Esta página describe los tres contextos y cómo diferenciarlos.
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 operadores.
Tipo de operador | Comportamiento | Dónde puedes usarlo |
|---|---|---|
expresión | Se evalúa sobre cada documento de entrada y devuelve un valor por documento. |
|
acumulador | Agrega datos sobre un grupo de documentos de entrada y devuelve un valor agregado por grupo. | |
Función de ventana | Se evalúa sobre una ventana de documentos de entrada y devuelve un valor por documento. |
|
Expresiones
Una expresión se resuelve en un valor para un único documento de entrada. Las expresiones no modifican sus entradas.
Los operadores de expresiones aceptan una matriz de argumentos y tienen la siguiente forma genérica:
{ <operator>: [ <argument1>, <argument2> ... ] }Si un operador acepta un solo argumento, puede omitir el array 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 obtener más información, consulte Expresiones.
Acumuladores
Un acumulador calcula un único valor agregado, como la suma, el máximo o el mínimo, a partir de un número variable de documentos de entrada. En implementaciones prácticas, los acumuladores mantienen un estado entre los documentos que procesan mientras ejecutan una operación de agrupación.
El número de documentos de salida que devuelve una etapa $group es igual al número de grupos. Para cada uno de estos grupos, un acumulador calcula un valor agregado para todo el grupo.
Puedes utilizar acumuladores en las etapas de la canalización de agregación que realizan operaciones de agrupación:
Para obtener más información,consulte Acumuladores.
Funciones de ventana
Una función de ventana devuelve un valor basado en una ventana, que es un intervalo de documentos definido en relación con el documento actual. La ventana se define con los campos 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é valores agrega el operador y cuántos valores devuelve:
Como acumulador, el operador agrega información sobre un grupo de documentos y devuelve un único valor para dicho grupo.
Como función de ventana, el operador agrega datos sobre una ventana de documentos y devuelve un valor para cada documento.
Puedes usar funciones de ventana solo en la etapa $setWindowFields. $setWindowFields también admite operadores específicos de ventanas, como $rank y $shift.
Para obtener más información, consulte 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 ejemplos utilizan $sum en los tres contextos. Cada uno devuelve un resultado diferente, lo que demuestra cómo el contexto determina el comportamiento de un operador.
Ejemplo de expresión
El siguiente ejemplo utiliza $sum como expresión para agregar dos campos dentro de cada documento. El proceso 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 todos los documentos de cada grupo. El proceso devuelve un total para cada calificació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 calcular el total de un campo en un conjunto de documentos. El proceso devuelve un total acumulado para cada documento, y dicho total depende del tamaño 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 } }] )