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



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


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.


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" }}});

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"}
        }
    }
])

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


2
db.collection.findOne().sort({age:-1}) //get Max without need for limit(1)

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": "roopak@small-screen.com",
      "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": "roopak@small-screen.com",
      "fullName": "Roopak Kapoor"
    }
  ],
  "Latest_Wish_CreatedDate": "2017-03-05T00:00:00.000Z"
},

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

0

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

db.collection.aggregate([{$sort:{age:-1}}, {$limit:1}])

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.