MongoDB के फाइंड और फाइंड कॉल के बीच अंतर


34

मैं एक प्रोजेक्ट पर काम कर रहा हूं और मैं अनिश्चित हूं अगर findकर्सर के काम करने के तरीके और कर्सर के काम करने के तरीके में अंतर होता है findOne। FindOne के लिए सिर्फ एक आवरण है find().limit(1)? मैं इसके लिए चारों ओर देख रहा था और शायद किसी को पता है कि मोंगोडब के पास इसके लिए एक विशेष तरीका है या नहीं। मैं mongodb के लिए PHP API के साथ काम कर रहा हूँ अगर इससे कोई फर्क पड़ता है।

जवाबों:


33

अपने स्वयं के बेंचमार्क के आधार पर, find().limit(1)परिमाण की तुलना में अधिक तेज़ी के आदेश हैं findOne()

MongoDB दस्तावेज़ में कोई त्रुटि है या बग में है findOne()findOne()और अधिक की तरह find().limit(N)जहां एन दस्तावेजों की संख्या क्वेरी वापस आ जाएगी है। मुझे यह पता लगाने की कोशिश करते हुए पता चला कि मेरे सरल प्रश्न इतने धीमे क्यों थे!

अद्यतन: एक 10gen (MongoDB) इंजीनियर से प्रतिक्रिया:

आपके द्वारा निष्पादित किए जा रहे दो प्रश्न बहुत अलग हैं। एक खोज क्वेरी एक कर्सर लौटाती है, यह अनिवार्य रूप से एक नो-ऑपरेशन परिदृश्य है, क्योंकि कोई वास्तविक डेटा वापस नहीं किया जाता है (केवल कर्सर जानकारी)। यदि आप findOne कहते हैं, तो आप वास्तव में डेटा वापस कर रहे हैं और कर्सर को बंद कर रहे हैं। डॉक्स निश्चित रूप से स्पष्ट होना चाहिए :-)

अद्यतन: वास्तव में, यदि find().limit(1)दस्तावेज़ को पुनर्प्राप्त किया जाता है, तो परिमाण गति अंतर के आदेश गायब हो जाते हैं। इसके अलावा, मैं MongoDB जावास्क्रिप्ट ड्राइवर के साथ प्रमुख गति अंतर को पुन: उत्पन्न नहीं कर सका। मैं मूल रूप से MongoDB Java ड्राइवर का उपयोग करके बेंचमार्क हुआ।


1
शानदार खोज। महत्वपूर्ण प्रश्न, हालांकि: क्या आपके बेंचमार्क find().limit(1)को सामान्य प्रोग्रामिंग (जैसे वास्तव में डेटा को पुनः प्राप्त करना और कर्सर को बंद करना) के अतिरिक्त कार्यों के लिए करना है जो findOne()स्वचालित रूप से आपके लिए करता है?
निक चामास

@ निक: मुझे लगता है कि अतिरिक्त ऑपरेशन कवर किए गए थे। मुझे एक यादृच्छिक दस्तावेज़ मिल रहा था ( cookbook.mongodb.org/patterns/random-attribute ), .next () के साथ दस्तावेज़ प्राप्त कर रहा है और संग्रह से निकाल रहा है। मैंने मैन्युअल रूप से किसी भी
शाप देने वाले को

@Leftium तो मुझे यह पूछना चाहिए कि क्या यह तेजी से एक find.limit (1) है और फिर घूस मूल्य प्राप्त करता है या यह एक Findone () करने के लिए तेज है
WojonsTech

2
@WojonsTech: JS में एक त्वरित बेंचमार्क showOne () वास्तव में तेज है। परिणाम ड्राइवर / प्लेटफॉर्म द्वारा भिन्न हो सकते हैं, हालांकि। उदाहरण के लिए, मैं जेएस में परिमाण गति अंतर के आदेशों को पुन: पेश नहीं कर सका जो मैंने मूल रूप से जावा चालक के साथ मनाया था।
लेफ्टियम

2
लेमियम, मैं आपके उत्तर को इस तनाव के लिए संपादित करूंगा कि जब आप वास्तव में दस्तावेज (जो आप सामान्य रूप से प्राप्त करेंगे) को पुनः प्राप्त करते हैं, तो दो कार्य वास्तव में समान हैं, जैसे कि दस्तावेज में कहा गया है। अभी कोई आपके उत्तर की शुरुआत में बोल्ड लाइन को पढ़ेगा और यह निष्कर्ष निकालेगा कि यदि वे एक दस्तावेज़ को पुनः प्राप्त करना चाहते हैं, तो findOne()वह इससे भी बदतर है find().limit(1), जो गलत है।
निक चामास

5

findOne()के लिए वास्तव में वाक्य रचना चीनी है find().limit(1), यह देखते हुए कि आप वास्तव में दस्तावेज़ को पुनः प्राप्त कर रहे हैं (जैसा कि सिर्फ कर्सर को वापस करने के विपरीत है find())।

अधिक विस्तार के लिए लेफ्टियम का उत्तर और अपडेट देखें ।


ठीक है, धन्यवाद, मुझे अपनी प्रोग्रामिंग में सिनिमस फ़ंक्शंस का उपयोग करना पसंद नहीं है, बल्कि खुद को एक सीमा में रखना होगा ताकि मेरा सभी कोड नीचे ट्रैक करना आसान हो।
वोजोन्सटेक

1
वास्तव में बेंचमार्क findOne () खोजने की तुलना में थोड़ा तेज है ()। सीमा (1)।
व्लादिमीर

@ DairT'arg - यदि आपके पास इस दावे का समर्थन करने के लिए स्रोत या डेटा हैं, तो हर तरह से विवरण के साथ उत्तर पोस्ट करें! मैंने अब तक जो भी इकट्ठा किया है, वे तब तक समान होने चाहिए जब तक आप दोनों मामलों में दस्तावेज़ को पुनः प्राप्त नहीं कर रहे हैं।
निक चामास

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और फिर पहले वापस आ जाता है।


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.