MongoDB'nin bul ve bul aramaları arasındaki fark


34

Bir proje üzerinde findçalışıyorum ve imlecin çalışma şekli ile imlecin çalışma şekli arasında bir fark olup olmadığından emin değilim findOne. FindOne sadece bir paketleyici find().limit(1)midir? Etrafını araştırıyordum ve belki birisi Mongodb'un bunun için özel bir yöntemi olup olmadığını biliyor. Bu fark yaratırsa, mongodb için PHP API ile çalışıyorum.

Yanıtlar:


33

Kendi karşılaştırmalarına göre, find().limit(1)büyüklük sıralaması ise daha hızlı daha findOne().

MongoDB belgelerinde bir hata veya içinde bir hata var findOne(). N'nin sorgunun döndüreceği belge sayısı olduğu findOne()gibi daha fazlasını gerçekleştirir find().limit(N). Basit sorgularımın neden bu kadar yavaş olduğunu anlamaya çalışırken bunu anladım!

güncelleme: bir 10gen (MongoDB) mühendisinden gelen cevap:

Yürütmekte olduğunuz iki sorgu çok farklı. Bulma sorgusu bir imleç döndürür, asıl veri döndürülmediğinden esasen işlemsiz bir senaryodur (sadece imleç bilgisi). FindOne'u çağırırsanız, aslında verileri döndürüyorsunuz ve imleci kapatıyorsunuzdur. Dokümanlar kesinlikle daha net olmalı :-)

Güncelleme: Aslında, find().limit(1)belge alınırsa, büyüklükteki hız farklarının sıraları yok gibi görünüyor. Ayrıca, MongoDB JavaScript sürücüsü ile ana hız farkını yeniden üretemedim. Aslında MongoDB Java sürücüsünü kullanarak kıyaslama yaptım.


1
Harika bul Önemli soru, yine de: Kriterleriniz find().limit(1)normal programlama sırasında yapmanız gereken ilave işlemleri (aslında verileri almak ve imleci kapatmak gibi) findOne()sizin için otomatik olarak yapan şeyleri hesaba katar mı?
Nick Chammas

@Nick: Ekstra operasyonların ele alındığını düşünüyorum. Rasgele bir belge buluyordum ( cookbook.mongodb.org/patterns/random-attribute ), belgeyi .next () ile alıyor ve koleksiyondan kaldırıyordum. Herhangi bir imleci manüel olarak kapatmadım ...
Leftium

@Leftium daha sonra sormam gereken bir find.limit (1) yapmak ve daha sonra cursur değerini almak mı yoksa bir findone yapmak için daha mı hızlı ()
WojonsTech

2
@WojonsTech: JS'deki hızlı bir değerlendirme, findOne () öğesinin gerçekten daha hızlı olduğunu gösterir. Yine de sonuçlar sürücüye / platforma göre değişebilir. Örneğin, JS'de orijinal olarak Java sürücüsü ile gözlemlediğim büyüklük farkı farklarının sırasını çoğaltamıyordum.
Leftium

2
Leftium, cevabınızı, gerçekte belgeyi aldığınızda (normalde yaptığınız gibi), iki fonksiyonun tıpkı dokümantasyonda olduğu gibi özdeş olduğunu vurgulamak için düzenlerdim. Şu anda birileri muhtemelen cevabınızın başında kalın satırları okuyacak ve bir belge almak istiyorlarsa yanlış findOne()olandan daha kötü olduğu sonucuna find().limit(1)varacak.
Nick Chammas

5

findOne()(imleci sadece geri döndürmenin tersine) , gerçekte belgeyi aldığınızdan dolayı , gerçekten sözdizimsel bir şekerdir .find().limit(1)find()

Daha fazla ayrıntı için Leftium'un cevabına ve güncellemelerine bakın.


tamam teşekkür ederim, programlamamda synimus fonksiyonlarını kullanmaktan hoşlanmıyorum, bir tanesini kendim koymayı tercih ederim, bu yüzden tüm kodumu bulmak kolaydır.
WojonsTech

1
Aslında benchmarklarda findOne (), find (). Limitinden (1) biraz daha hızlıdır.
Vladimir

@ DairT'arg - Bu iddiayı destekleyecek kaynak veya verileriniz varsa, elbette ayrıntılara bir cevap gönderin! Şimdiye kadar topladıklarımdan , her iki durumda da belgeyi aldığınız sürece onlar aynı olmalıdır .
Nick Chammas

3

Kaynak kodu çok yardımcı olabilir.

Java ama sanırım da yardımcı olabilir.

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

Ve işte find()

public DBCursor find( DBObject ref ){
    return new DBCursor( this, ref, null, getReadPreference());
}

Biz de görebileceğiniz gibi findOne()aramaları find()onun içinde kendini tüm alır DBOjectiçinde ive daha sonra ilk dönün.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.