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