Perbedaan antara panggilan find dan findo MongoDB

34

Saya mengerjakan proyek dan saya tidak yakin apakah ada perbedaan antara cara findkursor bekerja dan cara findOnekursor bekerja. Apakah findOne hanya pembungkus find().limit(1)? Saya mencari-cari dan mungkin seseorang tahu apakah mongodb memiliki metode khusus untuk itu atau tidak. Saya bekerja dengan API PHP untuk mongodb jika itu membuat perbedaan.

WojonsTech
sumber

Jawaban:

33

Berdasarkan tolok ukur saya sendiri, find().limit(1)apakah urutan besarnya lebih cepat dari findOne().

Ada kesalahan dalam dokumentasi MongoDB atau bug di findOne(). findOne()melakukan lebih banyak seperti di find().limit(N)mana N adalah jumlah dokumen permintaan akan kembali. Saya menemukan ini saat mencoba mencari tahu mengapa pertanyaan sederhana saya sangat lambat!

pembaruan: respons dari insinyur 10gen (MongoDB):

Dua pertanyaan yang Anda jalankan sangat berbeda. Query find mengembalikan kursor, ini pada dasarnya adalah skenario tanpa operasi, karena tidak ada data aktual yang dikembalikan (hanya informasi kursor). Jika Anda memanggil findOne, maka Anda sebenarnya mengembalikan data dan menutup kursor. Dokumen pasti harus lebih jelas :-)

Pembaruan: Memang, jika find().limit(1)dokumen itu diambil, urutan perbedaan kecepatan besarnya tampaknya menghilang. Juga, saya tidak dapat mereproduksi perbedaan kecepatan utama dengan driver JavaScript MongoDB. Saya awalnya diperbandingkan menggunakan driver Java MongoDB.

Leftium
sumber
1
Great ditemukan. Namun, pertanyaan penting: Apakah akun benchmark Anda untuk operasi tambahan yang harus Anda lakukan find().limit(1)dalam pemrograman normal (seperti benar-benar mengambil data dan menutup kursor) yang findOne()secara otomatis tetap melakukannya untuk Anda?
Nick Chammas
@Nick: Saya pikir operasi tambahan tercakup. Saya menemukan dokumen acak ( cookbook.mongodb.org/patterns/random-attribute ), mendapatkan dokumen dengan .next () dan menghapusnya dari koleksi. Saya tidak secara manual menutup kursor mana pun ...
Leftium
@Leftium maka saya harus bertanya apakah lebih cepat untuk melakukan find.limit (1) dan kemudian mendapatkan nilai cursur atau lebih cepat untuk melakukan findone ()
WojonsTech
2
@WojonsTech: patokan cepat di JS menunjukkan findOne () sebenarnya lebih cepat. Hasil dapat bervariasi berdasarkan driver / platform. Sebagai contoh, saya tidak bisa mereproduksi perintah perbedaan kecepatan magnitudo di JS yang awalnya saya amati dengan driver Java.
Leftium
2
Leftium, saya akan mengedit jawaban Anda untuk menekankan bahwa ketika Anda benar-benar mengambil dokumen (yang biasanya Anda lakukan), kedua fungsi tersebut sebenarnya identik, seperti yang dinyatakan oleh dokumentasi. Saat ini seseorang mungkin akan membaca baris tebal di awal jawaban Anda dan menyimpulkan bahwa jika mereka ingin mengambil satu dokumen, findOne()itu lebih buruk daripada find().limit(1), yang salah.
Nick Chammas
5

findOne()memang gula sintaksis untuk find().limit(1), mengingat bahwa Anda benar-benar mengambil dokumen (bukan hanya mengembalikan kursor dengan find()).

Lihat jawaban dan pembaruan Leftium untuk lebih detail.

Nick Chammas
sumber
oke terima kasih saya tidak suka menggunakan fungsi synimus dalam pemrograman saya lebih suka menempatkan batas sendiri jadi semua kode saya mudah dilacak.
WojonsTech
1
Sebenarnya dalam tolok ukur findOne () sedikit lebih cepat daripada find (). Batas (1).
Vladimir
@ DairT'arg - Jika Anda memiliki sumber atau data untuk mendukung klaim ini, silakan kirimkan jawaban dengan detail! Dari apa yang telah saya kumpulkan sejauh ini, mereka harus identik selama Anda mengambil dokumen dalam kedua kasus.
Nick Chammas
3

Kode sumber mungkin banyak membantu.

Ini java tapi saya kira itu bisa membantu juga.

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

Dan ini dia find()

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

Seperti yang kita lihat bahwa findOne()panggilan find()di dalamnya diri, mendapat semua DBOjectdi idan kemudian kembali yang pertama.

shellbye
sumber