ความแตกต่างระหว่างการค้นหาและการค้นหาของ MongoDB


34

ฉันทำงานในโครงการและฉันไม่แน่ใจว่ามีความแตกต่างระหว่างวิธีการfindทำงานของเคอร์เซอร์และวิธีการfindOneทำงานของเคอร์เซอร์ findOne เป็นเพียงแค่เสื้อคลุมfind().limit(1)หรือไม่? ฉันมองไปรอบ ๆ และอาจมีคนรู้ว่า mongodb มีวิธีพิเศษสำหรับมันหรือไม่ ฉันกำลังทำงานกับ PHP API สำหรับ MongoDB หากนั่นสร้างความแตกต่าง

คำตอบ:


33

ขึ้นอยู่กับมาตรฐานของตัวเองfind().limit(1)เป็นคำสั่งของขนาดได้เร็วfindOne()กว่า

มีทั้งข้อผิดพลาดในเอกสาร MongoDB findOne()หรือข้อผิดพลาดใน findOne()ดำเนินการมากขึ้นเช่นเดียวกับfind().limit(N)ที่ N คือจำนวนเอกสารที่แบบสอบถามจะส่งคืน ฉันพบสิ่งนี้ในขณะที่พยายามหาสาเหตุที่ข้อความค้นหาง่าย ๆ ของฉันช้ามาก!

อัปเดต: การตอบกลับจากวิศวกร 10gen (MongoDB):

แบบสอบถามสองรายการที่คุณกำลังดำเนินการนั้นแตกต่างกันมาก แบบสอบถามการค้นหาส่งคืนเคอร์เซอร์ซึ่งเป็นสถานการณ์สมมติที่ไม่มีการดำเนินการเนื่องจากไม่มีการส่งคืนข้อมูลจริง (เฉพาะข้อมูลเคอร์เซอร์) ถ้าคุณโทรหา findOne แสดงว่าคุณส่งคืนข้อมูลจริงและปิดเคอร์เซอร์ เอกสารควรชัดเจน :-)

อัปเดต:แน่นอนหากfind().limit(1)เอกสารถูกดึงมาคำสั่งของความเร็วที่แตกต่างกันดูเหมือนว่าจะหายไป นอกจากนี้ฉันไม่สามารถสร้างความแตกต่างความเร็วที่สำคัญกับไดรเวอร์ MongoDB JavaScript ฉันใช้เบนช์มาร์กมาตรฐาน MongoDB ในตอนแรก


1
หาที่ดี แต่คำถามสำคัญ: ทำเบนช์มาร์กของคุณสำหรับการปฏิบัติการพิเศษที่คุณต้องทำfind().limit(1)ในการเขียนโปรแกรมปกติหรือไม่ (เช่นการดึงข้อมูลและการปิดเคอร์เซอร์) ที่findOne()ทำเพื่อคุณโดยอัตโนมัติหรือไม่?
Nick Chammas

@ นิค: ฉันคิดว่าการปฏิบัติการพิเศษได้รับการคุ้มครอง ผมกำลังหาเอกสารแบบสุ่ม ( cookbook.mongodb.org/patterns/random-attribute ) ได้รับเอกสารที่มี .next () และถอดออกจากคอลเลกชัน ฉันไม่ได้ปิดเคอร์เซอร์ใด ๆ ด้วยตนเอง ...
Leftium

@Leftium แล้วฉันต้องถามว่ามันเร็วกว่าที่จะทำ find.limit (1) แล้วรับค่าเคอร์เซอร์หรือมันเร็วกว่าที่จะทำ findone ()
WojonsTech

2
@WojonsTech: มาตรฐานอย่างรวดเร็วใน JS แสดงให้เห็น findOne () เป็นจริงได้เร็วขึ้น แม้ว่าผลลัพธ์อาจแตกต่างกันไปตามไดรเวอร์ / แพลตฟอร์ม ตัวอย่างเช่นฉันไม่สามารถทำซ้ำคำสั่งของความเร็วที่แตกต่างกันใน JS ที่ฉันสังเกตเห็นครั้งแรกกับไดรเวอร์ Java
Leftium

2
Leftium ฉันจะแก้ไขคำตอบของคุณเพื่อเน้นว่าเมื่อคุณดึงเอกสารจริง (ซึ่งปกติคุณจะ) ทั้งสองฟังก์ชั่นจะเหมือนกันจริง ๆ เช่นเดียวกับเอกสารประกอบของรัฐ ตอนนี้คนที่มีแนวโน้มที่จะอ่านเส้นหนาที่จุดเริ่มต้นของคำตอบของคุณและสรุปได้ว่าถ้าพวกเขาต้องการที่จะเรียกเอกสารหนึ่งfindOne()เลวร้ายยิ่งกว่าfind().limit(1)ซึ่งไม่ถูกต้อง
Nick Chammas

5

findOne()ย่อมเป็นน้ำตาลประโยคสำหรับfind().limit(1), กำหนดว่าคุณเป็นจริงการเรียกเอกสาร (เมื่อเทียบกับเพียงแค่กลับเคอร์เซอร์ด้วยfind())

ดูคำตอบและอัพเดตของ Leftiumสำหรับรายละเอียดเพิ่มเติม


โอเคขอบคุณที่ฉันไม่ชอบการใช้ฟังก์ชั่นซิงมัสในการเขียนโปรแกรมของฉันค่อนข้างจะ จำกัด ตัวเองเพียงเพื่อให้รหัสของฉันง่ายต่อการติดตาม
WojonsTech

1
ในเกณฑ์มาตรฐานจริง findOne () เร็วกว่า find (). limit (1) เล็กน้อย
วลาดิมีร์

@ DairT'arg - หากคุณมีแหล่งข้อมูลหรือสำรองข้อมูลการอ้างสิทธิ์นี้โดยทุกคนโพสต์คำตอบพร้อมรายละเอียด! จากสิ่งที่ฉันรวบรวมมาพวกเขาควรเหมือนกันตราบใดที่คุณดึงเอกสารในทั้งสองกรณี
Nick Chammas

3

ซอร์สโค้ดอาจช่วยได้มาก

มันเป็นจาวา แต่ฉันคิดว่ามันสามารถช่วยได้เช่นกัน

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

และนี่คือ find()

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

ในฐานะที่เราจะเห็นว่าfindOne()สายfind()ในตัวเองได้รับทั้งหมดDBOjectในiแล้วกลับคนแรก


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.