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

Operador de canalización de agregación $avg de MongoDB

En MongoDB, el $avg El operador de canalización de agregación calcula y devuelve el valor promedio de los valores numéricos especificados.

Sintaxis

El $avg operador admite dos sintaxis.

Sintaxis 1:

{ $avg: <expression> }

Sintaxis 2:

{ $avg: [ <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, $avg devuelve el promedio colectivo de todos los valores numéricos que resultan de aplicar una expresión específica 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 $avg junto con $group para obtener el promedio de un grupo de documentos agrupados 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 $avg para devolver el peso promedio de cada grupo:

db.pets.aggregate(
   [
     {
       $group:
          {
            _id: "$type",
            average_weight: { $avg: "$weight" }
          }
     }
   ]
)

Resultado:

{ "_id" : "Dog", "average_weight" : 20 }
{ "_id" : "Cat", "average_weight" : 9 }
{ "_id" : "Kangaroo", "average_weight" : 143.33333333333334 }

Arreglos

Este ejemplo aplica $avg 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 $avg a las scores campo en cada documento:

db.players.aggregate(
   [
     {
       $project:
          {
            player: 1,
            averageScore: { $avg: "$scores" }
          }
     }
   ]
)

Resultado:

{ "_id" : 1, "player" : "Homer", "averageScore" : 4.142857142857143 }
{ "_id" : 2, "player" : "Marge", "averageScore" : 8.666666666666666 }
{ "_id" : 3, "player" : "Bart", "averageScore" : 6.333333333333333 }
{ "_id" : 4, "player" : "Brian", "averageScore" : 7 }
{ "_id" : 5, "player" : "Farnsworth", "averageScore" : null }
{ "_id" : 6, "player" : "Meg", "averageScore" : null }
{ "_id" : 7, "player" : "Ron", "averageScore" : null }

En este caso, los primeros cuatro documentos devolvieron el promedio 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ó null porque proporcionamos una matriz vacía.

El documento 6 devolvió null porque proporcionamos null como argumento.

El documento 7 devolvió null porque el campo ni siquiera existía.

Ejemplo de sintaxis 2 (múltiples argumentos)

La segunda sintaxis consiste en proporcionar $avg con más de un argumento. $avg luego calcula el promedio basado en todos los argumentos suministrados.

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 $avg para devolver el promedio de a , b , c y d campos de cada documento:

db.data.aggregate(
   [
     {
       $project:
          {
            avg: { $avg: [ "$a", "$b", "$c", "$d" ] }
          }
     }
   ]
)

Resultado:

{ "_id" : 1, "avg" : 2.5 }
{ "_id" : 2, "avg" : 2 }
{ "_id" : 3, "avg" : 2 }
{ "_id" : 4, "avg" : null }

El documento 1 devuelve el promedio de los valores de entrada de 1 , 2 , 3 y 4 .

Sin embargo, los siguientes dos documentos solo devolvieron el promedio de los valores de entrada de 1 , 2 y 3 . El $avg el operador ignoró su d los campos.

Esto se debe a que $avg ignora los valores no numéricos. Entonces, en este caso, ignoró "Hey" en el documento 3 y calculó el promedio de los campos (numéricos) restantes.

En cuanto al documento 2, es d campo contiene una matriz. Como se mencionó, el $avg 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 $avg ignora los valores no numéricos.

Si todos los valores no son numéricos, entonces $avg devuelve null . Podemos ver esto con el documento 4.

Campos faltantes

Al usar la sintaxis de múltiples argumentos, $avg ignora cualquier campo faltante. Es decir, si proporciona un campo que no existe, lo ignora. Si ninguno de los campos existe, devuelve null .

Ejemplo:

db.data.aggregate(
   [
     {
       $project:
          {
            avg: { $avg: [ "$a", "$b", "$c", "$d", "$e" ] }
          }
     }
   ]
)

Resultado:

{ "_id" : 1, "avg" : 2.5 }
{ "_id" : 2, "avg" : 2 }
{ "_id" : 3, "avg" : 2 }
{ "_id" : 4, "avg" : null }

En este caso proporcioné un campo extra ($e ) que no existe en los documentos. $avg calculó el promedio 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: { $avg: [ "$x", "$y", "$z" ] }
          }
     }
   ]
)

Resultado:

{ "_id" : 1, "result" : null }
{ "_id" : 2, "result" : null }
{ "_id" : 3, "result" : null }
{ "_id" : 4, "result" : null }

El resultado es null para todos los documentos.

Como vimos anteriormente, al usar la sintaxis de un solo argumento, un campo faltante da como resultado null .

Ejemplo:

db.pets.aggregate(
   [
     {
       $group:
          {
            _id: "$type",
            avg: { $avg: "$oops!" }
          }
     }
   ]
)

Resultado:

{ "_id" : "Kangaroo", "avg" : null }
{ "_id" : "Cat", "avg" : null }
{ "_id" : "Dog", "avg" : null }

Etapas disponibles

$avg está disponible en las siguientes etapas:

  • $group
  • $project
  • $addFields
  • $set
  • $replaceRoot
  • $replaceWith
  • $match etapa que incluye un $expr expresión