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

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

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