mongodb jak uzyskać maksymalną wartość z kolekcji


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


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ę.


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

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


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

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


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

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

1

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

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

3
To ma straszną wydajność. Uzyskanie najwyższej wartości zawsze kosztuje O(n)bez wskazań. To ma występO(n log(n))
sb27
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.