En MongoDB, el $sum
El operador de tubería de agregación calcula y devuelve la suma de valores numéricos.
Sintaxis
El $sum
operador admite dos sintaxis.
Sintaxis 1:
{ $sum: <expression> }
Sintaxis 2:
{ $sum: [ <expression1>, <expression2> ... ] }
La primera sintaxis acepta un argumento y la segunda sintaxis acepta múltiples argumentos.
Cuando se usa en el $group
etapa, solo puede usar la primera sintaxis. En este caso, $sum
devuelve la suma colectiva de todos los valores numéricos que resultan de aplicar la expresión especificada a cada documento en un grupo de documentos que comparten el mismo grupo por clave.
Ejemplos de sintaxis 1 (argumento único)
Aquí hay un par de ejemplos que usan la sintaxis 1.
Documentos agrupados
Este ejemplo usa $sum
junto con $group
para devolver la suma a través de un grupo de documentos que se agrupan por clave.
Supongamos que tenemos una colección llamada pets
con los siguientes documentos:
{ "_id" : 1, "name" : "Wag", "type" : "Dog", "weight" : 20 } { "_id" : 2, "name" : "Bark", "type" : "Dog", "weight" : 10 } { "_id" : 3, "name" : "Meow", "type" : "Cat", "weight" : 7 } { "_id" : 4, "name" : "Scratch", "type" : "Cat", "weight" : 8 } { "_id" : 5, "name" : "Bruce", "type" : "Kangaroo", "weight" : 100 } { "_id" : 6, "name" : "Hop", "type" : "Kangaroo", "weight" : 130 } { "_id" : 7, "name" : "Punch", "type" : "Kangaroo", "weight" : 200 } { "_id" : 8, "name" : "Snap", "type" : "Cat", "weight" : 12 } { "_id" : 9, "name" : "Ruff", "type" : "Dog", "weight" : 30 }
Podemos agrupar estos documentos por su type
y luego use $sum
para devolver la suma del weight
campo para cada grupo:
db.pets.aggregate(
[
{
$group:
{
_id: "$type",
sum: { $sum: "$weight" }
}
}
]
)
Resultado:
{ "_id" : "Kangaroo", "sum" : 430 } { "_id" : "Cat", "sum" : 27 } { "_id" : "Dog", "sum" : 60 }
Arreglos
Este ejemplo aplica $sum
a un solo documento que contiene un campo con una matriz de valores.
Esta opción solo está disponible cuando se utiliza la sintaxis de argumento único. Las matrices se ignoran cuando se usa la sintaxis de múltiples argumentos (más sobre esto a continuación).
Supongamos que tenemos una colección llamada players
con los siguientes documentos:
{ "_id" : 1, "player" : "Homer", "scores" : [ 1, 7, 2, 3, 8, 7, 1 ] } { "_id" : 2, "player" : "Marge", "scores" : [ 0, 1, 8, 17, 18, 8 ] } { "_id" : 3, "player" : "Bart", "scores" : [ 15, 11, 8, 0, 1, 3 ] } { "_id" : 4, "player" : "Brian", "scores" : [ 7 ] } { "_id" : 5, "player" : "Farnsworth", "scores" : [ ] } { "_id" : 6, "player" : "Meg", "scores" : null } { "_id" : 7, "player" : "Ron" }
Podemos aplicar $sum
a las scores
campo en cada documento:
db.players.aggregate(
[
{
$project:
{
player: 1,
sum: { $sum: "$scores" }
}
}
]
)
Resultado:
{ "_id" : 1, "player" : "Homer", "sum" : 29 } { "_id" : 2, "player" : "Marge", "sum" : 52 } { "_id" : 3, "player" : "Bart", "sum" : 38 } { "_id" : 4, "player" : "Brian", "sum" : 7 } { "_id" : 5, "player" : "Farnsworth", "sum" : 0 } { "_id" : 6, "player" : "Meg", "sum" : 0 } { "_id" : 7, "player" : "Ron", "sum" : 0 }
En este caso, los primeros cuatro documentos devolvieron la suma de varios números que estaban en sus respectivas matrices.
En el caso del documento 4, este era el mismo que el número, porque solo había un número en la matriz.
El documento 5 devolvió 0
porque proporcionamos una matriz vacía.
El documento 6 devolvió 0
porque proporcionamos null
como argumento.
El documento 7 devolvió 0
porque el campo ni siquiera existía.
Ejemplo de sintaxis 2 (múltiples argumentos)
La segunda sintaxis consiste en proporcionar $sum
con más de un argumento. $sum
luego calcula la suma basada en todos los argumentos provistos.
Supongamos que tenemos una colección llamada data
con los siguientes documentos:
{ "_id" : 1, "a" : 1, "b" : 2, "c" : 3, "d" : 4 } { "_id" : 2, "a" : 1, "b" : 2, "c" : 3, "d" : [ 4 ] } { "_id" : 3, "a" : 1, "b" : 2, "c" : 3, "d" : "Hey" } { "_id" : 4, "a" : "One", "b" : "Two", "c" : "Three", "d" : "Four" }
Podemos usar $sum
para devolver la suma de a
, b
, c
y d
campos de cada documento:
db.data.aggregate(
[
{
$project:
{
sum: { $sum: [ "$a", "$b", "$c", "$d" ] }
}
}
]
)
Resultado:
{ "_id" : 1, "sum" : 10 } { "_id" : 2, "sum" : 6 } { "_id" : 3, "sum" : 6 } { "_id" : 4, "sum" : 0 }
El documento 1 devuelve la suma de los valores de entrada de 1
, 2
, 3
y 4
.
Sin embargo, los siguientes dos documentos solo devolvieron la suma de los valores de entrada de 1
, 2
y 3
. El $sum
el operador ignoró su d
los campos.
Esto se debe a que $sum
ignora los valores no numéricos. Entonces, en este caso, ignoró "Hey"
en el documento 3 y calculó la suma de los campos (numéricos) restantes.
En cuanto al documento 2, es d
campo contiene una matriz. Como se mencionó, el $sum
El operador ignora las matrices cuando usa la sintaxis de múltiples argumentos. Más precisamente, trata las matrices como valores no numéricos cuando se usa en este contexto, y $sum
ignora los valores no numéricos.
Si todos los valores no son numéricos, entonces $sum
devuelve 0
. Podemos ver esto con el documento 4.
Campos faltantes
Al usar la sintaxis de múltiples argumentos, $sum
ignora cualquier campo faltante. Es decir, si proporciona un campo que no existe, lo ignora. Si ninguno de los campos existe, devuelve 0
.
Ejemplo:
db.data.aggregate(
[
{
$project:
{
sum: { $sum: [ "$a", "$b", "$c", "$d", "$e" ] }
}
}
]
)
Resultado:
{ "_id" : 1, "sum" : 10 } { "_id" : 2, "sum" : 6 } { "_id" : 3, "sum" : 6 } { "_id" : 4, "sum" : 0 }
En este caso proporcioné un campo extra ($e
) que no existe en los documentos. $sum
calculó la suma en función de los campos restantes que hacen existir.
Sin embargo, esto es lo que sucede cuando ninguno de los campos existen:
db.data.aggregate(
[
{
$project:
{
result: { $sum: [ "$x", "$y", "$z" ] }
}
}
]
)
Resultado:
{ "_id" : 1, "result" : 0 } { "_id" : 2, "result" : 0 } { "_id" : 3, "result" : 0 } { "_id" : 4, "result" : 0 }
El resultado es 0
para todos los documentos.
Como vimos anteriormente, al usar la sintaxis de un solo argumento, un campo faltante da como resultado 0
.
Ejemplo:
db.pets.aggregate(
[
{
$group:
{
_id: "$type",
sum: { $sum: "$oops!" }
}
}
]
)
Resultado:
{ "_id" : "Cat", "sum" : 0 } { "_id" : "Dog", "sum" : 0 } { "_id" : "Kangaroo", "sum" : 0 }
Etapas disponibles
$sum
está disponible en las siguientes etapas:
$group
$project
$addFields
$set
$replaceRoot
$replaceWith
$match
etapa que incluye un$expr
expresión