In MongoDB, il $sum
l'operatore della pipeline di aggregazione calcola e restituisce la somma dei valori numerici.
Sintassi
Il $sum
operatore supporta due sintassi.
Sintassi 1:
{ $sum: <expression> }
Sintassi 2:
{ $sum: [ <expression1>, <expression2> ... ] }
La prima sintassi accetta un argomento e la seconda sintassi accetta più argomenti.
Se utilizzato nel $group
stage, puoi usare solo la prima sintassi. In questo caso, $sum
restituisce la somma collettiva di tutti i valori numerici risultanti dall'applicazione dell'espressione specificata a ciascun documento in un gruppo di documenti che condividono lo stesso gruppo per chiave.
Esempi di sintassi 1 (argomento singolo)
Ecco un paio di esempi che utilizzano la sintassi 1.
Documenti raggruppati
Questo esempio usa $sum
insieme a $group
per restituire la somma in un gruppo di documenti raggruppati per chiave.
Supponiamo di avere una collezione chiamata pets
con i seguenti documenti:
{ "_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 }
Possiamo raggruppare questi documenti in base al loro type
campo, quindi utilizzare $sum
per restituire la somma del weight
campo per ogni gruppo:
db.pets.aggregate(
[
{
$group:
{
_id: "$type",
sum: { $sum: "$weight" }
}
}
]
)
Risultato:
{ "_id" : "Kangaroo", "sum" : 430 } { "_id" : "Cat", "sum" : 27 } { "_id" : "Dog", "sum" : 60 }
Array
Questo esempio applica $sum
in un singolo documento che contiene un campo con una matrice di valori.
Questa opzione è disponibile solo quando si utilizza la sintassi di argomento singolo. Gli array vengono ignorati quando si utilizza la sintassi multi-argomento (ne parleremo più avanti).
Supponiamo di avere una collezione chiamata players
con i seguenti documenti:
{ "_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" }
Possiamo applicare $sum
ai scores
campo in ogni documento:
db.players.aggregate(
[
{
$project:
{
player: 1,
sum: { $sum: "$scores" }
}
}
]
)
Risultato:
{ "_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 }
In questo caso, i primi quattro documenti hanno restituito la somma dei vari numeri che erano nei rispettivi array.
Nel caso del documento 4, questo era lo stesso del numero, perché c'era un solo numero nell'array.
Il documento 5 ha restituito 0
perché abbiamo fornito un array vuoto.
Il documento 6 ha restituito 0
perché abbiamo fornito null
come argomento.
Il documento 7 ha restituito 0
perché il campo non esisteva nemmeno.
Esempio di sintassi 2 (argomenti multipli)
La seconda sintassi prevede di fornire $sum
con più di un argomento. $sum
quindi calcola la somma in base a tutti gli argomenti forniti.
Supponiamo di avere una raccolta chiamata data
con i seguenti documenti:
{ "_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" }
Possiamo usare $sum
per restituire la somma di a
, b
, c
e d
campi di ogni documento:
db.data.aggregate(
[
{
$project:
{
sum: { $sum: [ "$a", "$b", "$c", "$d" ] }
}
}
]
)
Risultato:
{ "_id" : 1, "sum" : 10 } { "_id" : 2, "sum" : 6 } { "_id" : 3, "sum" : 6 } { "_id" : 4, "sum" : 0 }
Il documento 1 restituisce la somma dei valori di input di 1
, 2
, 3
e 4
.
Tuttavia, i due documenti successivi hanno restituito solo la somma dei valori di input di 1
, 2
e 3
. Il $sum
l'operatore ha ignorato il suo d
campi.
Questo perché $sum
ignora i valori non numerici. Quindi in questo caso ha ignorato "Hey"
nel documento 3 e calcolato la somma dai restanti campi (numerici).
Come per il documento 2, il suo d
campo contiene una matrice. Come accennato, il $sum
l'operatore ignora gli array quando si utilizza la sintassi multi-argomento. Più precisamente, tratta gli array come valori non numerici se usati in questo contesto e $sum
ignora i valori non numerici.
Se tutti i valori non sono numerici, allora $sum
restituisce 0
. Possiamo vederlo con il documento 4.
Campi mancanti
Quando si utilizza la sintassi multi-argomento, $sum
ignora tutti i campi mancanti. Cioè, se fornisci un campo che non esiste, lo ignora. Se nessuno dei campi esiste, restituisce 0
.
Esempio:
db.data.aggregate(
[
{
$project:
{
sum: { $sum: [ "$a", "$b", "$c", "$d", "$e" ] }
}
}
]
)
Risultato:
{ "_id" : 1, "sum" : 10 } { "_id" : 2, "sum" : 6 } { "_id" : 3, "sum" : 6 } { "_id" : 4, "sum" : 0 }
In questo caso ho fornito un campo aggiuntivo ($e
) che non esiste nei documenti. $sum
calcolato la somma in base ai campi rimanenti che fanno esistono.
Tuttavia, ecco cosa succede quando nessuno dei campi esistono:
db.data.aggregate(
[
{
$project:
{
result: { $sum: [ "$x", "$y", "$z" ] }
}
}
]
)
Risultato:
{ "_id" : 1, "result" : 0 } { "_id" : 2, "result" : 0 } { "_id" : 3, "result" : 0 } { "_id" : 4, "result" : 0 }
Il risultato è 0
per tutti i documenti.
Come abbiamo visto in precedenza, quando si utilizza la sintassi a argomento singolo, un campo mancante risulta in 0
.
Esempio:
db.pets.aggregate(
[
{
$group:
{
_id: "$type",
sum: { $sum: "$oops!" }
}
}
]
)
Risultato:
{ "_id" : "Cat", "sum" : 0 } { "_id" : "Dog", "sum" : 0 } { "_id" : "Kangaroo", "sum" : 0 }
Stadi disponibili
$sum
è disponibile nelle seguenti fasi:
$group
$project
$addFields
$set
$replaceRoot
$replaceWith
$match
fase che include un$expr
espressione