sql >> Base de Datos >  >> NoSQL >> MongoDB

Operador de tubería de agregación MongoDB $sum

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