Różnica między szukaniem MongoDB a szukaniem findone
34
Pracuję nad projektem i nie jestem pewien, czy istnieje różnica między sposobem działania findkursora a działaniem findOnekursora. Czy findOne to tylko opakowanie find().limit(1)? Rozglądałem się i może ktoś wie, czy mongodb ma do tego specjalną metodę, czy nie. Pracuję z PHP API dla mongodb, jeśli to robi różnicę.
W oparciu o moje własne testy porównawcze find().limit(1)jest o rząd wielkości szybszy niż findOne().
Wystąpił błąd w dokumentacji MongoDB lub błąd w findOne(). findOne()działa bardziej jak find().limit(N)gdzie N to liczba dokumentów, które zwróci zapytanie. Zrozumiałem to, próbując dowiedzieć się, dlaczego moje proste zapytania były tak wolne!
Dwa wykonywane zapytania są bardzo różne. Zapytanie wyszukujące zwraca kursor, jest to zasadniczo scenariusz braku operacji, ponieważ żadne rzeczywiste dane nie są zwracane (tylko informacje o kursorze). Jeśli wywołasz findOne, w rzeczywistości zwracasz dane i zamykasz kursor. Dokumenty powinny zdecydowanie być jaśniejsze :-)
Aktualizacja: Rzeczywiście, jeśli find().limit(1)dokument zostanie pobrany, wydaje się, że różnica prędkości rzędu rzędów zniknie. Ponadto nie mogłem odtworzyć głównej różnicy prędkości ze sterownikiem JavaScript MongoDB. Początkowo testowałem przy użyciu sterownika Java MongoDB.
Świetne znalezisko. Ważne pytanie: czy twoje testy porównawcze uwzględniają dodatkowe operacje, które musiałbyś wykonać find().limit(1)w trakcie normalnego programowania (np. Pobieranie danych i zamykanie kursora), które findOne()i tak robią automatycznie?
Nick Chammas,
@Nick: Myślę, że dodatkowe operacje zostały objęte. Znalazłem przypadkowy dokument ( cookbook.mongodb.org/patterns/random-attribute ), pobrałem dokument za pomocą .next () i usunąłem go z kolekcji. Nie
zamknąłem
@Leftium to muszę zapytać, czy szybciej jest znaleźć find.limit (1), a następnie uzyskać wartość cursur, czy też szybciej jest zrobić findone ()
WojonsTech
2
@WojonsTech: szybki test porównawczy w JS pokazuje findOne () jest faktycznie szybszy. Wyniki mogą się jednak różnić w zależności od sterownika / platformy. Na przykład nie mogłem odtworzyć rzędu różnicy prędkości rzędu JS, który zaobserwowałem pierwotnie ze sterownikiem Java.
Leftium
2
Leftium, zredagowałbym twoją odpowiedź, aby podkreślić, że kiedy faktycznie pobierasz dokument (co normalnie byś zrobił), obie funkcje są w rzeczywistości identyczne, tak jak stwierdza dokumentacja. W tej chwili ktoś prawdopodobnie przeczyta pogrubioną linię na początku twojej odpowiedzi i stwierdzi, że jeśli chce odzyskać jeden dokument, findOne()jest gorszy niż find().limit(1), co jest niepoprawne.
Nick Chammas
5
findOne()jest rzeczywiście cukier syntaktyczny dla find().limit(1), biorąc pod uwagę, że jesteś rzeczywiście pobierania dokumentu (w przeciwieństwie do po prostu powrocie z kursorem find()).
Zobacz odpowiedź i aktualizacje Leftium, aby uzyskać więcej szczegółów.
ok, dziękuję, nie lubię używać funkcji synimus w moim programowaniu, wolę sam ustawić limit jeden, aby cały mój kod był łatwy do wyśledzenia.
WojonsTech,
1
Właściwie w testach porównawczych findOne () jest nieco szybszy niż find (). Limit (1).
Vladimir
@ DairT'arg - Jeśli masz źródła lub dane, aby wykonać kopię zapasową tego roszczenia, zdecydowanie opublikuj odpowiedź ze szczegółami! Z tego, co do tej pory zebrałem, powinny być identyczne, o ile w obu przypadkach pobierasz dokument.
Nick Chammas,
3
Kod źródłowy może bardzo pomóc.
To java, ale myślę, że to też może pomóc.
findOne(),
DBObject findOne(DBObject o, DBObject fields, DBObject orderBy, ReadPreference readPref,
long maxTime, TimeUnit maxTimeUnit){
QueryOpBuilder queryOpBuilder = new QueryOpBuilder().addQuery(o).addOrderBy(orderBy).addMaxTimeMS(MILLISECONDS.convert(maxTime, maxTimeUnit));if(getDB().getMongo().isMongosConnection()){
queryOpBuilder.addReadPreference(readPref);}
Iterator<DBObject> i = find(queryOpBuilder.get(), fields,0,-1,0, getOptions(), readPref, getDecoder());
DBObject obj =(i.hasNext()? i.next():null);if( obj !=null&&( fields !=null&& fields.keySet().size()>0)){
obj.markAsPartialObject();}return obj;}
I oto jest find()
public DBCursor find( DBObject ref ){return new DBCursor( this, ref,null, getReadPreference());}
Jak widzimy, że findOne()połączenia find()w to samo, dostaje wszystkie DBOjectw i, a następnie powrót pierwszego.
find().limit(1)
w trakcie normalnego programowania (np. Pobieranie danych i zamykanie kursora), którefindOne()
i tak robią automatycznie?findOne()
jest gorszy niżfind().limit(1)
, co jest niepoprawne.findOne()
jest rzeczywiście cukier syntaktyczny dlafind().limit(1)
, biorąc pod uwagę, że jesteś rzeczywiście pobierania dokumentu (w przeciwieństwie do po prostu powrocie z kursoremfind()
).Zobacz odpowiedź i aktualizacje Leftium, aby uzyskać więcej szczegółów.
źródło
Kod źródłowy może bardzo pomóc.
To java, ale myślę, że to też może pomóc.
findOne()
,I oto jest
find()
Jak widzimy, że
findOne()
połączeniafind()
w to samo, dostaje wszystkieDBOject
wi
, a następnie powrót pierwszego.źródło
Musisz sprawdzić ten link ...
http://mongoosejs.com/docs/2.7.x/docs/finding-documents.html
źródło