mongodb cómo obtener el valor máximo de las colecciones

81

Tengo una colección de mongodb como:

db.kids.find()
//results
[
    {name:'tom', age:10},
    {name:'alice', age:12},
    ....
]

Necesito una consulta para obtener MAX 'edad' de esta colección como en SQL: SELECT MAX(age) FROM kids WHERE 1

Hossain Khademian
fuente
9
puede usardb.collection.find().sort({age:-1}).limit(1)
Vishwas

Respuestas:

119

Como uno de los comentarios :

db.collection.find().sort({age:-1}).limit(1) // for MAX
db.collection.find().sort({age:+1}).limit(1) // for MIN

es completamente utilizable pero no estoy seguro de su rendimiento

Hossain Khademian
fuente
9
En el caso de una colección grande, es mejor definir un índice en el agecampo. Entonces, si lo usa db.collection.find({}, {age: 1, _id:0}).sort({age:-1}).limit(1), probablemente tenga una consulta cubierta
Ali Dehghani
@AliDehghani ¿Funcionaría este método en fragmentos de mongo?
igonejack
68

El desempeño de la respuesta sugerida está bien. Según la documentación de MongoDB :

Cuando un $ sort precede inmediatamente a un $ limit , el optimizador puede fusionar el $ limit en el $ sort. Esto permite que la operación de clasificación solo mantenga los primeros n resultados a medida que avanza, donde n es el límite especificado , y MongoDB solo necesita almacenar n elementos en la memoria.

Modificado en la versión 4.0.

Entonces en el caso de

db.collection.find().sort({age:-1}).limit(1)

obtenemos solo el elemento más alto SIN ordenar la colección debido a la optimización mencionada.

popolvar
fuente
6
ese enlace de documentación es para agregación. ¿Estás seguro de que find( ... ).sort( ... ).limit( ... )se trata de la misma forma que aggregate([{$match: ... }, {$sort: ...}, {$limit: ...}])? ¿Hay algún lugar en los documentos de Mongo en el que mencionen esto?
jmmut
25

¿qué pasa con el uso de marco agregado:

db.collection.aggregate({ $group : { _id: null, max: { $max : "$age" }}});
moribundo
fuente
18
Esto no es tan eficiente como sort.limit. Aún así, sé que en el fondo todos se sienten extraños con ese tipo y límite ...
AFP_555
@ AFP_555 Realmente me sorprende saber que el agregado es más lento que una consulta de límite de clasificación. ¡Gracias por compartir!
Nam G VU
1
¿Es el agregado más lento que la consulta de límite de clasificación?
ashusvirus
1
Hago el caso de prueba simple. Crea una colección con 1.000.000 de documentos {nombre: "jugador", puntuación: x}. El .find (). Sort ({score: -1}). Limit (1); toma más tiempo que .aggregate ([{$ group: {_id: null, max: {$ max: "$ score"}}}])
tuananh
3
@tuananh, esto puede suceder si no tienes un índice de "puntuación". En este caso, sort tendrá que realizar operaciones O (n log n), mientras que el agregado solo hará un escaneo O (n). Con el campo indexado, sort (...). Limit (1) será una operación de tiempo constante O (1) muy rápida.
cababunga
9

puedes usar group y max:

db.getCollection('kids').aggregate([
    {
        $group: {
            _id: null,
            maxQuantity: {$max: "$age"}
        }
    }
])
lvks2012
fuente
La misma respuesta ya se dio hace casi un año.
Dan Dascalescu
1
La otra respuesta similar no parece funcionar, esta sintaxis sí lo hace
Zach Smith
3

Amigos, pueden ver lo que está haciendo el optimizador ejecutando un plan. El formato genérico de buscar en un plan es de la documentación de MongoDB . es decir, Cursor.plan (). Si realmente desea profundizar, puede hacer un cursor.plan (verdadero) para obtener más detalles.

Dicho esto, si tiene un índice, su db.col.find (). Sort ({"field": - 1}). Limit (1) leerá una entrada de índice, incluso si el índice es ascendente predeterminado y desea la entrada máxima y un valor de la colección.

En otras palabras, las sugerencias de @yogesh son correctas.

Gracias - Sumit

Sumit S
fuente
2
db.collection.findOne().sort({age:-1}) //get Max without need for limit(1)
Hisham
fuente
4
Al menos en Mongo 4.2, esa sintaxis le dará un TypeError: db.collection.findOne(...).sort is not a function. collection.findOne () devuelve el documento en sí, por lo que llamar a sort () parece poco probable que funcione.
Peter Hansen
1

Explicación simple, si tiene una respuesta de consulta mongo como la siguiente, y solo desea el valor más alto de Array-> "Fecha"

{
  "_id": "57ee5a708e117c754915a2a2",
  "TotalWishs": 3,
  "Events": [
    "57f805c866bf62f12edb8024"
  ],
  "wish": [
    "Cosmic Eldorado  Mountain Bikes, 26-inch (Grey/White)",
    "Asics Men's Gel-Nimbus 18 Black, Snow and Fiery Red Running Shoes - 10 UK/India (45 EU) (11 US)",
    "Suunto Digital Black Dial Unisex Watch - SS018734000"
  ],
  "Date": [
    "2017-02-13T00:00:00.000Z",
    "2017-03-05T00:00:00.000Z"
  ],
  "UserDetails": [
    {
      "createdAt": "2016-09-30T12:28:32.773Z",
      "jeenesFriends": [
        "57edf8a96ad8f6ff453a384a",
        "57ee516c8e117c754915a26b",
        "58a1644b6c91d2af783770b0",
        "57ef4631b97d81824cf54795"
      ],
      "userImage": "user_profile/Male.png",
      "email": "[email protected]",
      "fullName": "Roopak Kapoor"
    }
  ],

},

*** Entonces has añadido

Latest_Wish_CreatedDate: {$ max: "$ Date"},

algo como abajo

{ 
                $project : { _id: 1,
                             TotalWishs : 1 ,
                              wish:1 ,
                               Events:1, 
                               Wish_CreatedDate:1,
                               Latest_Wish_CreatedDate: { $max: "$Date"},
                            } 
            } 

Y la respuesta de consulta final estará debajo

{
  "_id": "57ee5a708e117c754915a2a2",
  "TotalWishs": 3,
  "Events": [
    "57f805c866bf62f12edb8024"
  ],
  "wish": [
    "Cosmic Eldorado  Mountain Bikes, 26-inch (Grey/White)",
    "Asics Men's Gel-Nimbus 18 Black, Snow and Fiery Red Running Shoes - 10 UK/India (45 EU) (11 US)",
    "Suunto Digital Black Dial Unisex Watch - SS018734000"
  ],
  "Wish_CreatedDate": [
    "2017-03-05T00:00:00.000Z",
    "2017-02-13T00:00:00.000Z"
  ],
  "UserDetails": [
    {
      "createdAt": "2016-09-30T12:28:32.773Z",
      "jeenesFriends": [
        "57edf8a96ad8f6ff453a384a",
        "57ee516c8e117c754915a26b",
        "58a1644b6c91d2af783770b0",
        "57ef4631b97d81824cf54795"
      ],
      "userImage": "user_profile/Male.png",
      "email": "[email protected]",
      "fullName": "Roopak Kapoor"
    }
  ],
  "Latest_Wish_CreatedDate": "2017-03-05T00:00:00.000Z"
},
Shashwat Gupta
fuente
1

Para un valor máximo, podemos escribir la consulta SQL como

select age from table_name order by age desc limit 1

de la misma manera también podemos escribir en mongodb.

db.getCollection('collection_name').find().sort({"age" : -1}).limit(1); //max age
db.getCollection('collection_name').find().sort({"age" : 1}).limit(1); //min age
Kankatala Krishna
fuente
0

También puede lograr esto a través de una canalización agregada.

db.collection.aggregate([{$sort:{age:-1}}, {$limit:1}])
prakash soleado
fuente
3
Esto tiene un rendimiento terrible. Obtener el valor más alto siempre cuesta O(n)sin índices. Esto tiene una actuación deO(n log(n))
sb27