Definición
Modificado en la versión 5.0.
Calcula y devuelve la suma total de valores numéricos. El $sum ignora los valores no numéricos.
$sum está disponible en estas etapas:
$setWindowFields(Disponible a partir de MongoDB 5.0)
Compatibilidad
Puedes usar $sum para implementaciones alojadas en los siguientes entornos:
MongoDB Atlas: El servicio totalmente gestionado para implementaciones de MongoDB en la nube
MongoDB Enterprise: La versión basada en suscripción y autogestionada de MongoDB
MongoDB Community: La versión de MongoDB con código fuente disponible, de uso gratuito y autogestionada.
Sintaxis
Cuando se utiliza como un acumulador, $sum tiene esta sintaxis:
{ $sum: <expression> }
Cuando no se utiliza como un acumulador, $sum tiene esta sintaxis:
{ $sum: [ <expression1>, <expression2> ... ] }
Para obtener más información sobre las expresiones, consulta Expresiones.
Comportamiento
Tipo de datos del resultado
El resultado tendrá el mismo tipo que la entrada excepto cuando no pueda representarse con precisión en ese tipo. En estos casos:
Un entero de 32bits se convertirá en un entero de 64bits si el resultado se puede representar como un entero de 64bits.
Un entero de 32bits se convertirá en un doble si el resultado no se puede representar como un entero de 64bits.
Un entero de 64bits se convertirá en doble si el resultado no se puede representar como un entero de 64bits.
Campos no numéricos o no existentes
Si se utiliza en un campo que contiene tanto valores numéricos como no numéricos, $sum ignora los valores no numéricos y devuelve la suma de los valores numéricos.
Si se utiliza en un campo que no existe en ningún documento de la colección, $sum devuelve 0 para ese campo.
Si todos los operandos no son numéricos, no son arreglos o contienen valores null, $sum devuelve 0. Para obtener detalles sobre cómo $sum gestiona los arreglos, consulta Operando de arreglo.
Arreglo Operand
En la etapa $group, si la expresión se resuelve en un arreglo, $sum trata el operando como un valor no numérico.
En las otras etapas admitidas:
Con una única expresión como operando, si la expresión se resuelve en un arreglo,
$sumrecorre el arreglo para operar sobre sus elementos numéricos y devolver un único valor.Con una lista de expresiones como su operando, si alguna de las expresiones se resuelve en un arreglo,
$sumno recorre el arreglo sino que lo trata como un valor no numérico.
Por ejemplo, cuando no se utiliza en una etapa $group:
Si el operando
$sumes[ 2, 2 ],$sumsuma los elementos del arreglo y devuelve 4.Si el operando
$sumes[ 2, [ 3, 4 ] ],$sumdevuelve 2 porque trata el arreglo anidado[ 3, 4 ]como un valor no numérico.
Ejemplos
Usar en la etapa $group
Considera una colección sales con los siguientes documentos:
db.sales.insertMany( [ { "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2, "date" : ISODate("2014-01-01T08:00:00Z") }, { "_id" : 2, "item" : "jkl", "price" : 20, "quantity" : 1, "date" : ISODate("2014-02-03T09:00:00Z") }, { "_id" : 3, "item" : "xyz", "price" : 5, "quantity" : 5, "date" : ISODate("2014-02-03T09:05:00Z") }, { "_id" : 4, "item" : "abc", "price" : 10, "quantity" : 10, "date" : ISODate("2014-02-15T08:00:00Z") }, { "_id" : 5, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-02-15T09:05:00Z") } ] )
Al agrupar los documentos por el día y el año del campo date, la siguiente operación utiliza el acumulador $sum para calcular el importe total y el recuento de cada grupo de documentos.
db.sales.aggregate( [ { $group: { _id: { day: { $dayOfYear: "$date"}, year: { $year: "$date" } }, totalAmount: { $sum: { $multiply: [ "$price", "$quantity" ] } }, count: { $sum: 1 } } } ] )
La operación devuelve los siguientes resultados:
{ "_id" : { "day" : 46, "year" : 2014 }, "totalAmount" : 150, "count" : 2 } { "_id" : { "day" : 34, "year" : 2014 }, "totalAmount" : 45, "count" : 2 } { "_id" : { "day" : 1, "year" : 2014 }, "totalAmount" : 20, "count" : 1 }
El uso de $sum en un campo inexistente devuelve un valor de 0. La siguiente operación intenta $sum sobre qty:
db.sales.aggregate( [ { $group: { _id: { day: { $dayOfYear: "$date"}, year: { $year: "$date" } }, totalAmount: { $sum: "$qty" }, count: { $sum: 1 } } } ] )
La operación arroja:
{ "_id" : { "day" : 46, "year" : 2014 }, "totalAmount" : 0, "count" : 2 } { "_id" : { "day" : 34, "year" : 2014 }, "totalAmount" : 0, "count" : 2 } { "_id" : { "day" : 1, "year" : 2014 }, "totalAmount" : 0, "count" : 1 }
El acumulador de agregación $count se puede utilizar en lugar de { $sum : 1 } en la etapa de $group.
Usar en la etapa $project
Una colección students contiene los siguientes documentos:
{ "_id": 1, "quizzes": [ 10, 6, 7 ], "labs": [ 5, 8 ], "final": 80, "midterm": 75 } { "_id": 2, "quizzes": [ 9, 10 ], "labs": [ 8, 8 ], "final": 95, "midterm": 80 } { "_id": 3, "quizzes": [ 4, 5, 5 ], "labs": [ 6, 5 ], "final": 78, "midterm": 70 }
El siguiente ejemplo utiliza el $sum en la etapa $project para calcular las puntuaciones totales de los cuestionarios, las puntuaciones totales de los laboratorios y el total del examen final y del parcial:
db.students.aggregate([ { $project: { quizTotal: { $sum: "$quizzes"}, labTotal: { $sum: "$labs" }, examTotal: { $sum: [ "$final", "$midterm" ] } } } ])
La operación da como resultado los siguientes documentos:
{ "_id" : 1, "quizTotal" : 23, "labTotal" : 13, "examTotal" : 155 } { "_id" : 2, "quizTotal" : 19, "labTotal" : 16, "examTotal" : 175 } { "_id" : 3, "quizTotal" : 14, "labTotal" : 11, "examTotal" : 148 }
Usar en la etapa $setWindowFields
Nuevo en la versión 5.0.
Crea una colección de cakeSales que incluya ventas de pasteles en el estado de California (CA) y Washington (WA):
db.cakeSales.insertMany( [ { _id: 0, type: "chocolate", orderDate: new Date("2020-05-18T14:10:30Z"), state: "CA", price: 13, quantity: 120 }, { _id: 1, type: "chocolate", orderDate: new Date("2021-03-20T11:30:05Z"), state: "WA", price: 14, quantity: 140 }, { _id: 2, type: "vanilla", orderDate: new Date("2021-01-11T06:31:15Z"), state: "CA", price: 12, quantity: 145 }, { _id: 3, type: "vanilla", orderDate: new Date("2020-02-08T13:13:23Z"), state: "WA", price: 13, quantity: 104 }, { _id: 4, type: "strawberry", orderDate: new Date("2019-05-18T16:09:01Z"), state: "CA", price: 41, quantity: 162 }, { _id: 5, type: "strawberry", orderDate: new Date("2019-01-08T06:12:03Z"), state: "WA", price: 43, quantity: 134 } ] )
Este ejemplo utiliza $sum en la etapa $setWindowFields para generar la suma de las quantity de pasteles vendidos en cada state:
db.cakeSales.aggregate( [ { $setWindowFields: { partitionBy: "$state", sortBy: { orderDate: 1 }, output: { sumQuantityForState: { $sum: "$quantity", window: { documents: [ "unbounded", "current" ] } } } } } ] )
En el ejemplo:
partitionBy: "$state"particiona los documentos de la colección enstate. Existen particiones paraCAyWA.sortBy: { orderDate: 1 }ordena los documentos de cada partición pororderDateen orden ascendente (1), de modo que elorderDatemás antiguo sea el primero.
outputestablece el camposumQuantityForStatea la suma de los valores dequantityusando$sumque se ejecuta en una ventana de documentos.La ventana contiene documentos entre un límite inferior de
unboundedy el documentocurrenten el resultado. Esto significa que$sumdevuelve la suma de los valores dequantitypara los documentos entre el inicio de la partición y el documento actual.
En este resultado, la suma de los valores de quantity para CA y WA se muestra en el campo sumQuantityForState:
{ "_id" : 4, "type" : "strawberry", "orderDate" : ISODate("2019-05-18T16:09:01Z"), "state" : "CA", "price" : 41, "quantity" : 162, "sumQuantityForState" : 162 } { "_id" : 0, "type" : "chocolate", "orderDate" : ISODate("2020-05-18T14:10:30Z"), "state" : "CA", "price" : 13, "quantity" : 120, "sumQuantityForState" : 282 } { "_id" : 2, "type" : "vanilla", "orderDate" : ISODate("2021-01-11T06:31:15Z"), "state" : "CA", "price" : 12, "quantity" : 145, "sumQuantityForState" : 427 } { "_id" : 5, "type" : "strawberry", "orderDate" : ISODate("2019-01-08T06:12:03Z"), "state" : "WA", "price" : 43, "quantity" : 134, "sumQuantityForState" : 134 } { "_id" : 3, "type" : "vanilla", "orderDate" : ISODate("2020-02-08T13:13:23Z"), "state" : "WA", "price" : 13, "quantity" : 104, "sumQuantityForState" : 238 } { "_id" : 1, "type" : "chocolate", "orderDate" : ISODate("2021-03-20T11:30:05Z"), "state" : "WA", "price" : 14, "quantity" : 140, "sumQuantityForState" : 378 }