mongodb jak uzyskać maksymalną wartość z kolekcji

87

Mam kolekcję Mongodb, taką jak:

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

Potrzebuję zapytania, aby uzyskać MAX `` wiek '' z tej kolekcji, jak w SQL: SELECT MAX(age) FROM kids WHERE 1

Hossain Khademian
źródło
9
możesz użyćdb.collection.find().sort({age:-1}).limit(1)
Vishwas

Odpowiedzi:

125

Jako jeden z komentarzy :

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

jest w pełni użyteczny, ale nie jestem pewien co do wydajności

Hossain Khademian
źródło
11
W przypadku dużej kolekcji lepiej jest zdefiniować indeks na agepolu. W takim razie, jeśli użyjesz db.collection.find({}, {age: 1, _id:0}).sort({age:-1}).limit(1), prawdopodobnie otrzymasz bardzo szybkie zapytanie objęte
usługą
@AliDehghani Czy ta metoda działa na odłamkach mongo?
igonejack
72

Wydajność sugerowanej odpowiedzi jest w porządku. Zgodnie z dokumentacją MongoDB :

Kiedy sortowanie $ bezpośrednio poprzedza limit $ , optymalizator może połączyć limit $ w sortowanie $. Dzięki temu operacja sortowania może zachować tylko n pierwszych wyników w miarę postępu, gdzie n jest określonym limitem , a MongoDB musi przechowywać tylko n elementów w pamięci.

Zmieniono w wersji 4.0.

Tak więc w przypadku

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

otrzymujemy tylko najwyższy element BEZ sortowania kolekcji ze względu na wspomnianą optymalizację.

popolvar
źródło
7
to łącze do dokumentacji służy do agregacji. Czy na pewno find( ... ).sort( ... ).limit( ... )jest traktowany tak samo jak aggregate([{$match: ... }, {$sort: ...}, {$limit: ...}])? czy jest jakieś miejsce w dokumentach mongo, że wspominają o tym?
jmmut
26

co z użyciem agregatu:

db.collection.aggregate({ $group : { _id: null, max: { $max : "$age" }}});
dier
źródło
21
To nie jest tak wydajne jak sort.limit. Mimo to wiem, że w głębi duszy każdy czuje się dziwnie z powodu tego rodzaju i ograniczenia ...
AFP_555,
@ AFP_555 Naprawdę zaskoczony faktem, że agregowanie jest wolniejsze niż zapytanie ograniczające sortowanie. Dzięki za udostępnienie!
Nam G VU
1
czy agregacja jest wolniejsza niż zapytanie ograniczające sortowanie?
ashusvirus
1
Robię prosty przypadek testowy. Utwórz kolekcję zawierającą 1 000 000 dokumentów {nazwa: "gracz", wynik: x}. .Find (). Sort ({wynik: -1}). Limit (1); zajmuje więcej czasu niż .aggregate ([{$ group: {_id: null, max: {$ max: "$ score"}}}])
tuananh
3
@tuananh, może się to zdarzyć, jeśli nie masz indeksu „score”. W tym przypadku sortowanie będzie musiało wykonać O (n log n) operacji, podczas gdy agregat wykona tylko jeden skan O (n). Z indeksowanym polem sort (...). Limit (1) będzie bardzo szybką operacją o stałym czasie O (1).
cababunga
10

możesz użyć grupy i max:

db.getCollection('kids').aggregate([
    {
        $group: {
            _id: null,
            maxQuantity: {$max: "$age"}
        }
    }
])
lvks2012
źródło
Ta sama odpowiedź została udzielona już prawie rok temu.
Dan Dascalescu,
1
Druga podobna odpowiedź wydaje się nie działać - ta składnia działa
Zach Smith
3
db.collection.findOne().sort({age:-1}) //get Max without need for limit(1)
Hisham
źródło
4
Przynajmniej w Mongo 4.2 ta składnia zapewni ci plik TypeError: db.collection.findOne(...).sort is not a function. collection.findOne () zwraca sam dokument, więc wywołanie sort () na nim wydaje się mało prawdopodobne.
Peter Hansen
3

Ludzie, możecie zobaczyć, co robi optymalizator, uruchamiając plan. Ogólny format przeglądania planu pochodzi z dokumentacji MongoDB . tj Cursor.plan(). Jeśli naprawdę chcesz sięgnąć głębiej, możesz zrobić cursor.plan(true)więcej szczegółów.

Powiedziawszy, że jeśli masz indeks, db.col.find().sort({"field":-1}).limit(1)przeczytasz jeden wpis indeksu - nawet jeśli indeks jest domyślnie rosnący i chcesz mieć maksymalny wpis i jedną wartość z kolekcji.

Innymi słowy, sugestie @yogesh są poprawne.

Dzięki - Sumit

Sumit S.
źródło
1

Proste wyjaśnienie, jeśli masz odpowiedź na zapytanie mongo, jak poniżej - i chcesz tylko najwyższą wartość z Array-> "Date"

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

},

*** Następnie musisz dodać

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

coś jak poniżej

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

Ostateczna odpowiedź na zapytanie będzie poniżej

{
  "_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
źródło
1

Dla wartości maksymalnej możemy napisać zapytanie sql jako

select age from table_name order by age desc limit 1

w ten sam sposób możemy również pisać w 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
źródło
1

Możesz to również osiągnąć poprzez zagregowany potok.

db.collection.aggregate([{$sort:{age:-1}}, {$limit:1}])
słoneczny prakash
źródło
3
To ma straszną wydajność. Uzyskanie najwyższej wartości zawsze kosztuje O(n)bez wskazań. To ma występO(n log(n))
sb27