En MongoDB, el $max
El operador de canalización de agregación devuelve el valor máximo de una expresión.
Sintaxis
El $max
operador admite dos sintaxis.
Sintaxis 1:
{ $max: <expression> }
Sintaxis 2:
{ $max: [ <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, $max
devuelve el valor máximo que resulta de aplicar una expresión 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 de un solo argumento.
Documentos agrupados
Este ejemplo usa $max
junto con $group
para devolver el valor máximo 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 $max
para devolver el valor máximo del weight
campo para cada grupo:
db.pets.aggregate(
[
{
$group:
{
_id: "$type",
max: { $max: "$weight" }
}
}
]
)
Resultado:
{ "_id" : "Kangaroo", "max" : 200 } { "_id" : "Cat", "max" : 12 } { "_id" : "Dog", "max" : 30 }
Arreglos
Este ejemplo aplica $max
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 $max
a las scores
campo en cada documento:
db.players.aggregate(
[
{
$project:
{
player: 1,
max: { $max: "$scores" }
}
}
]
)
Resultado:
{ "_id" : 1, "player" : "Homer", "max" : 8 } { "_id" : 2, "player" : "Marge", "max" : 18 } { "_id" : 3, "player" : "Bart", "max" : 15 } { "_id" : 4, "player" : "Brian", "max" : 7 } { "_id" : 5, "player" : "Farnsworth", "max" : null } { "_id" : 6, "player" : "Meg", "max" : null } { "_id" : 7, "player" : "Ron", "max" : null }
En este caso, los primeros cuatro documentos devolvieron el valor máximo de los diversos 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 $max
con más de un argumento. $max
luego devuelve el valor máximo de todos los argumentos proporcionados.
Supongamos que tenemos una colección llamada data
con el siguiente documento:
{ "_id" : 1, "a" : 10, "b" : 500, "c" : -900, "d" : 4 }
Podemos usar $max
para devolver el valor máximo de a
, b
, c
y d
campos:
db.data.aggregate(
[
{ $match: { _id: { $in: [ 1 ] } } },
{
$project:
{
max: { $max: [ "$a", "$b", "$c", "$d" ] }
}
}
]
)
Resultado:
{ "_id" : 1, "max" : 500 }
En este caso, 500
fue el valor máximo.
Campos faltantes
Al usar la sintaxis de varios argumentos, $max
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(
[
{ $match: { _id: { $in: [ 1 ] } } },
{
$project:
{
max: { $max: [ "$a", "$b", "$c", "$d", "$e" ] }
}
}
]
)
Resultado:
{ "_id" : 1, "max" : 500 }
En este caso proporcioné un campo extra ($e
) que no existe en el documento. $max
calculó el valor máximo 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(
[
{ $match: { _id: { $in: [ 1 ] } } },
{
$project:
{
result: { $max: [ "$x", "$y", "$z" ] }
}
}
]
)
Resultado:
{ "_id" : 1, "result" : null }
El resultado es null
.
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",
max: { $max: "$oops!" }
}
}
]
)
Resultado:
{ "_id" : "Dog", "max" : null } { "_id" : "Kangaroo", "max" : null } { "_id" : "Cat", "max" : null }
Comparando diferentes tipos
El $max
El operador compara tanto el valor como el tipo. Cuando los valores son de diferentes tipos, $max
calcula el valor máximo en función del orden de comparación de BSON.
Supongamos que nuestra colección contiene los siguientes documentos:
{ "_id" : 2, "a" : 1, "b" : 2, "c" : 3, "d" : [ 1 ] } { "_id" : 3, "a" : 1, "b" : 2, "c" : 3, "d" : "1" } { "_id" : 4, "a" : "One", "b" : "Two", "c" : "Three", "d" : "Four" } { "_id" : 5, "a" : ISODate("1999-01-03T23:30:15.100Z"), "b" : ISODate("2000-01-03T23:30:15.100Z") } { "_id" : 6, "a" : ISODate("1999-01-03T23:30:15.100Z"), "b" : "2000-01-03T23:30:15.100Z" }
Con la excepción del documento 4, cada uno de esos documentos usa tipos mixtos (hay al menos un tipo que es diferente a los demás en los campos de datos). El documento 4 usa cadenas en los cuatro campos.
Esto es lo que sucede cuando aplicamos $max
a esos documentos:
db.data.aggregate(
[
{ $match: { _id: { $in: [ 2, 3, 4, 5, 6 ] } } },
{
$project:
{
max: { $max: [ "$a", "$b", "$c", "$d" ] }
}
}
]
)
Resultado:
{ "_id" : 2, "max" : [ 1 ] } { "_id" : 3, "max" : "1" } { "_id" : 4, "max" : "Two" } { "_id" : 5, "max" : ISODate("2000-01-03T23:30:15.100Z") } { "_id" : 6, "max" : ISODate("1999-01-03T23:30:15.100Z") }
el documento con un _id
de 2
, las matrices son mayores que los números, por lo que se devuelve la matriz (aunque su elemento sea un número menor que algunos de los otros números).
Documento 3:las cadenas son mayores que los números, por lo que se devuelve la cadena.
Documento 4:Todos los campos son cadenas, por lo que Two
es la cadena más grande.
Documento 5:se proporcionan dos fechas, por lo que se devuelve la fecha posterior.
Documento 6:en este caso, se proporcionan un objeto Fecha y una cadena de fecha. Los objetos de fecha son mayores que las cadenas, por lo que se devuelve el objeto de fecha (aunque su fecha sea anterior a la de la cadena).
Etapas disponibles
$max
está disponible en las siguientes etapas:
$group
$project
$addFields
$set
$replaceRoot
$replaceWith
$match
etapa que incluye un$expr
expresión