क्या EntityFieldQuery वास्तव में यह अक्षम है?


11

मैं एंटिटी एपीआई में एक भर्ती नौसिखिया हूं, लेकिन मैं इसे ठीक करने की कोशिश कर रहा हूं। मैं एक ऐसी साइट पर काम कर रहा हूं, जिसमें कई तरह के कंटेंट टाइप हैं, जो उनके साथ जुड़े हुए विभिन्न क्षेत्रों में उपयोग होते हैं; कुछ भी आकर्षक नहीं। इसलिए, जब मैं प्रविष्टियों का एक सेट पुनः प्राप्त करना चाहता हूं, तो मैं अपने अज्ञान में, डेटाबेस में सीधे नीचे कॉल कर रहा हूं और इस तरह से कुछ कर रहा हूं:

$query = db_select('node', 'n')->extend('PagerDefault');
$query->fields('n', array('nid'));
$query->condition('n.type', 'my_content_type');

$query->leftJoin('field_data_field_user_role', 'role', 'n.nid = role.entity_id');
$query->condition('role.field_user_role_value', $some_value);

$query->leftJoin('field_data_field_withdrawn_time', 'wt', 'n.nid = wt.entity_id');
$query->condition('wt.field_withdrawn_time_value', 0);

$query->orderBy('n.created', 'desc');

$query->limit(10);

$result = $the_questions->execute()->fetchCol();

(हाँ, मैं शायद एक $the_questions->बयान में इन पंक्तियों के एक समूह को ध्वस्त कर सकता हूं ; pls अब के लिए इसे अनदेखा करें।

EntityFieldQuery के साथ इसे फिर से लिखने की कोशिश कर रहा हूं, मैं इसके साथ आता हूं:

$query = new EntityFieldQuery();
$query
  ->entityCondition('entity_type', 'node')
  ->entityCondition('bundle', 'my_content_type')
  ->fieldCondition('field_user_role', 'value', $some_value)
  ->fieldCondition('field_withdrawn_time', 'value', 0)
  ->propertyOrderBy('created', 'desc')
  ->pager(10);

$result = $query->execute();

if (isset($result['node'])) {
    $result_nids = array_keys($result['node']);
}
else {
    $result_nids = array();
}

जो मुझे वांछित परिणाम प्रदान करता है और निश्चित रूप से बहुत सुंदर है।

इसलिए, अब मैं प्रदर्शन के बारे में सोच रहा हूं। एक शुरुआत के रूप में, मैं कोड के उन बिट्स को एक बेवकूफ for()लूप में फेंक देता हूं , time()निष्पादन से पहले और बाद में कैप्चर करना । मैं प्रत्येक संस्करण को एक बहुत बड़े डेटाबेस से 100 बार चलाता हूं, और इस तरह से कुछ प्राप्त करता हूं:

  • सीधा संस्करण: 110 मिसे
  • EFQ संस्करण: 4943 मिसे

जाहिर है कि जब मैं दोबारा परीक्षा देता हूं तो मुझे अलग-अलग परिणाम मिलते हैं, लेकिन परिणाम लगातार एक ही बॉलपार्क में होते हैं।

ओह। क्या मैं यहाँ कुछ गलत कर रहा हूँ, या यह केवल EFQ का उपयोग करने की लागत है? मैंने सामग्री प्रकारों के संबंध में कोई विशेष डेटाबेस ट्यूनिंग नहीं की है; वे सिर्फ वही हैं जो सामान्य प्रकार, प्रपत्र-आधारित तरीके से सामग्री प्रकारों को परिभाषित करने से आता है। कोई विचार? EFQ कोड निश्चित रूप से क्लीनर है, लेकिन मुझे नहीं लगता कि मैं एक 40x प्रदर्शन हिट बर्दाश्त कर सकता हूं।


3
क्या आप दोनों उत्पन्न sql प्रश्नों को डंप कर सकते हैं?
आंद्रे बॉमिएर

1
देखें इस एक यदि आप सुनिश्चित कैसे एक EFQ की एसक्यूएल बाहर निकलने के लिए नहीं कर रहे हैं
क्लाइव

2
ठीक है, वहाँ प्रगति है: यहाँ क्या हो रहा है कि मेरी साइट पर नोड एक्सेस नियमों का एक गुच्छा है जो क्वेरी के आकार को काफी बढ़ा रहे हैं। वे स्वचालित रूप से EFQ क्वेरी पर लागू हो रहे थे (भले ही ->addTag('node_access')क्वेरी में कोई भी नहीं है ??)। मैं एक नोड_एसीट टैग के साथ "प्रत्यक्ष" क्वेरी को फिर से चलाता हूं, और निष्पादन समय बहुत करीब है: EFQ का समय अब ​​प्रत्यक्ष दृष्टिकोण से अधिक 2 के कारक के बारे में है, जो उचित रूप से सापेक्ष एसक्यूएल को देखते हुए लगता है कि दोनों बाहर पंप कर रहे हैं (जो मैं पोस्ट कर सकता हूं अगर लोग अभी भी परवाह करते हैं)। (अगली टिप्पणी पर चर्चा करेंगे ....)
जिम मिलर

तो अब सवाल है, मुझे लगता है, क्यों मैं स्वचालित रूप से EFQ संस्करण में node_access सामान प्राप्त कर रहा हूं? मैंने सोचा कि आपको स्पष्ट रूप से AddTag () क्लॉज के माध्यम से इसके लिए पूछना था ??
जिम मिलर

जवाबों:


10

EntityFieldQueryवर्ग के रूप में कुशल के रूप में अपनी आवश्यकताओं को यह होने की अनुमति है। इसे किसी भी फ़ील्ड स्टोरेज क्लासेस के साथ संगत करने की आवश्यकता है, यहां तक ​​कि उन लोगों के साथ भी जो फ़ील्ड डेटा संग्रहीत करने के लिए NoSQL इंजन का उपयोग करते हैं, जैसे कि MongoDB का उपयोग करता है । उस कारण से, EntityFieldQueryडेटाबेस को सीधे क्वेरी नहीं कर सकते, क्योंकि वर्तमान फ़ील्ड स्टोरेज बैकएंड SQL डेटाबेस का उपयोग बिल्कुल नहीं कर सकता है।

यहां तक ​​कि अगर क्षेत्र भंडारण अपने डेटा को संग्रहीत करने के लिए SQL इंजन का उपयोग करता है, $query->leftJoin('field_data_field_user_role', 'role', 'n.nid = role.entity_id'); $query->condition('role.field_user_role_value', $some_value);तो EntityFieldQueryकक्षा के लिए समकक्ष की आवश्यकता होती है:

  • फ़ील्ड नाम से डेटाबेस तालिका नाम बनाने के लिए कोड
  • इकाई डेटा वाली तालिका के साथ फ़ील्ड डेटा वाले तालिका में शामिल होने के लिए उपयोग करने के लिए कोड बनाने के लिए कोड
  • फ़ील्ड डेटा वाले डेटाबेस पंक्ति का नाम बनाने के लिए कोड

अंतर तुरंत दिखाई देता है: एक मामले में आप तीन लिटरल स्ट्रिंग्स का उपयोग कर रहे हैं, जबकि दूसरे मामले में कोड है कि (मामलों के सबसे सरल में) स्ट्रेंथनिंग है।

कोड के बारे में आपकी टिप्पणी के अनुसार, अगर जाँचता है कि उपयोगकर्ता के पास खेतों तक पहुँचने की अनुमति है, तो आप निम्न लाइन को EntityFieldQueryवर्ग का उपयोग करके कोड को बायपास कर सकते हैं ।

$query->addTag('DANGEROUS_ACCESS_CHECK_OPT_OUT');

यदि आप Drupal 7.15, या उच्चतर का उपयोग कर रहे हैं तो यह काम करता है; पहले के संस्करणों के लिए, आपको निम्नलिखित कोड का उपयोग करना चाहिए।

$account = user_load(1);
$query->addMetaData('account', $account);

हमेशा की तरह, आपको एक्सेस अनुमति को बायपास नहीं करना चाहिए यदि कोड उपयोगकर्ता को वह जानकारी दिखा सके, जिसमें उपयोगकर्ता की पहुंच नहीं होनी चाहिए। यह ड्रुपल से क्या होता है जब अप्रकाशित नोड केवल उन उपयोगकर्ताओं को दिखाया जाता है जिनके पास अप्रकाशित नोड्स को देखने की अनुमति है। यदि कोड का उद्देश्य है, उदाहरण के लिए, कुछ संस्थाओं को चुनना जो क्रमिक रूप से हटाए गए हैं (जैसे क्रोन कार्यों के दौरान), तो एक्सेस कंट्रोल पास करने से कोई नुकसान नहीं होता है, और यह आगे बढ़ने का एकमात्र तरीका है।


मुझे मानना ​​चाहिए कि मैं शायद सही नहीं हूं, क्योंकि पहली क्वेरी पेजर का उपयोग करती है, (मैं ->extend('PagerDefault');पहली बार नोटिस नहीं किया था)
mojzis

वूप्स, तुम सही हो।
kiamlaluno

यह मुझे वास्तव में दिलचस्पी है, इसलिए मैं ऊपर प्रयोग के कुछ लाइनों के साथ कोशिश कर रहा हूँ और कठबोली संख्या में भारी अंतर की पुष्टि कर सकता है ... क्या कोई इसे भी आज़मा सकता है, कृपया?
मोजजिस

तो, बस पुष्टि करने के लिए: EFQ कॉल हमेशा ही साइट के नोड एक्सेस नियमों को लागू करता है जब तक कि आप ऐसा करने के लिए कुछ नहीं करते हैं (जैसा कि ऊपर वर्णित है)। सही?
जिम मिलर

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