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ę.
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?
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).
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.
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
db.collection.find().sort({age:-1}).limit(1)
Odpowiedzi:
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
źródło
age
polu. W takim razie, jeśli użyjeszdb.collection.find({}, {age: 1, _id:0}).sort({age:-1}).limit(1)
, prawdopodobnie otrzymasz bardzo szybkie zapytanie objęteWydajność sugerowanej odpowiedzi jest w porządku. Zgodnie z dokumentacją MongoDB :
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ę.
źródło
find( ... ).sort( ... ).limit( ... )
jest traktowany tak samo jakaggregate([{$match: ... }, {$sort: ...}, {$limit: ...}])
? czy jest jakieś miejsce w dokumentach mongo, że wspominają o tym?co z użyciem agregatu:
db.collection.aggregate({ $group : { _id: null, max: { $max : "$age" }}});
źródło
możesz użyć grupy i max:
db.getCollection('kids').aggregate([ { $group: { _id: null, maxQuantity: {$max: "$age"} } } ])
źródło
db.collection.findOne().sort({age:-1}) //get Max without need for limit(1)
źródło
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.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
źródło
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ć
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" },
źródło
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
źródło
Możesz to również osiągnąć poprzez zagregowany potok.
db.collection.aggregate([{$sort:{age:-1}}, {$limit:1}])
źródło
O(n)
bez wskazań. To ma występO(n log(n))