mongodb wie man maximalen Wert aus Sammlungen bekommt

81

Ich habe eine Mongodb-Sammlung wie:

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

Ich benötige eine Abfrage, um MAX 'Alter' aus dieser Sammlung wie in SQL zu erhalten: SELECT MAX(age) FROM kids WHERE 1

Hossain Khademian
quelle
9
Sie können verwendendb.collection.find().sort({age:-1}).limit(1)
Vishwas

Antworten:

118

Als einer der Kommentare :

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

Es ist vollständig verwendbar, aber ich bin mir nicht sicher über die Leistung

Hossain Khademian
quelle
9
Bei einer großen Sammlung ist es besser, einen Index für das ageFeld zu definieren . Wenn Sie dann verwenden db.collection.find({}, {age: 1, _id:0}).sort({age:-1}).limit(1), hätten Sie wahrscheinlich eine sehr schnelle Covered Query
Ali Dehghani
@AliDehghani Würde diese Methode auf Mongo-Scherben funktionieren?
Igonejack
68

Die Leistung der vorgeschlagenen Antwort ist in Ordnung. Laut MongoDB-Dokumentation :

Wenn eine $ -Sortierung unmittelbar vor einem $ -Limit liegt , kann der Optimierer das $ -Limit zu der $ -Sortierung zusammenführen. Auf diese Weise kann die Sortieroperation im Verlauf nur die besten n Ergebnisse beibehalten , wobei n die angegebene Grenze ist und MongoDB nur n Elemente im Speicher speichern muss.

In Version 4.0 geändert.

Also im Fall von

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

Aufgrund der genannten Optimierung erhalten wir nur das höchste Element, OHNE die Sammlung zu sortieren.

Popolvar
quelle
6
Dieser Dokumentationslink dient zur Aggregation. Sind Sie sicher, dass find( ... ).sort( ... ).limit( ... )es genauso behandelt wird wie aggregate([{$match: ... }, {$sort: ...}, {$limit: ...}])? Gibt es irgendwo in den Mongo-Dokumenten einen Ort, an dem sie dies erwähnen?
Jmmut
25

Was ist mit der Verwendung eines aggregierten Frameworks?

db.collection.aggregate({ $group : { _id: null, max: { $max : "$age" }}});
dier
quelle
18
Dies ist nicht so effizient wie das sort.limit. Trotzdem weiß ich tief im
Inneren,
@ AFP_555 Wirklich überrascht zu wissen, dass das Aggregat langsamer ist als eine Sortierlimitabfrage. Danke für das Teilen!
Nam G VU
1
Ist das Aggregat langsamer als die Abfrage mit Sortierlimit?
Ashusvirus
1
Ich mache den einfachen Testfall. Erstellen Sie eine Sammlung mit 1.000.000 Dokumenten {Name: "Spieler", Punktzahl: x}. Die .find (). Sort ({score: -1}). Limit (1); Nehmen Sie sich mehr Zeit als .aggregate ([{$ group: {_id: null, max: {$ max: "$ score"}}})
tuananh
3
@tuananh, dies kann passieren, wenn Sie keinen Index für "Punktzahl" haben. In diesem Fall muss die Sortierung O (n log n) -Operationen ausführen, während das Aggregat nur einen Scan-O (n) ausführt. Bei einem indizierten Feld ist sort (...). Limit (1) eine sehr schnelle Operation mit konstanter Zeit O (1).
Cababunga
9

Sie können group und max verwenden:

db.getCollection('kids').aggregate([
    {
        $group: {
            _id: null,
            maxQuantity: {$max: "$age"}
        }
    }
])
lvks2012
quelle
Die gleiche Antwort wurde bereits vor fast einem Jahr gegeben.
Dan Dascalescu
1
Die andere ähnliche Antwort scheint nicht zu funktionieren - diese Syntax funktioniert
Zach Smith
3

Leute, Sie können sehen, was der Optimierer tut, indem Sie einen Plan ausführen. Das generische Format für die Prüfung eines Plans stammt aus der MongoDB- Dokumentation . dh Cursor.plan (). Wenn Sie wirklich tiefer graben möchten, können Sie einen cursor.plan (true) für weitere Details ausführen.

Wenn Sie jedoch einen Index haben, liest Ihre Datei db.col.find (). Sort ({"field": - 1}). Limit (1) einen Indexeintrag - auch wenn der Index standardmäßig aufsteigend ist und Sie dies wollten der maximale Eintrag und ein Wert aus der Sammlung.

Mit anderen Worten, die Vorschläge von @yogesh sind korrekt.

Danke - Sumit

Sumit S.
quelle
2
db.collection.findOne().sort({age:-1}) //get Max without need for limit(1)
Hisham
quelle
4
Zumindest in Mongo 4.2 erhalten Sie mit dieser Syntax eine TypeError: db.collection.findOne(...).sort is not a function. collection.findOne () gibt das Dokument selbst zurück, sodass es unwahrscheinlich ist, dass sort () darauf aufgerufen wird.
Peter Hansen
1

Einfache Erklärung, wenn Sie eine Mongo-Abfrage Antwort wie unten haben - und Sie nur den höchsten Wert von Array-> "Datum" wollen.

{
  "_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"
    }
  ],

},

*** Dann hast du hinzugefügt

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

so etwas wie unten-

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

Die endgültige Antwort auf die Abfrage finden Sie weiter unten

{
  "_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
quelle
1

Für den Maximalwert können wir eine SQL-Abfrage als schreiben

select age from table_name order by age desc limit 1

Ebenso können wir auch in Mongodb schreiben.

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
quelle
0

Sie können dies auch durch eine aggregierte Pipeline erreichen.

db.collection.aggregate([{$sort:{age:-1}}, {$limit:1}])
sonniges Prakash
quelle
2
Das hat eine schreckliche Leistung. Den höchsten Wert O(n)zu erzielen kostet immer ohne Angaben. Dies hat eine Leistung vonO(n log(n))
sb27