2016-09-12 9 views
15

मेरे पास एक क्वेरी है जो पर्याप्त रूप से काम करती है, लेकिन मैं क्वेरी पैराम और प्रश्न के क्षेत्र में लेवेनशेटिन का उपयोग कर इसके परिणामों को सॉर्ट करना चाहता हूं।लोचदार खोज: लेवेनशेटिन सॉर्टिंग

अभी मैं ईएस में क्वेरी कर रहा हूं और फिर मैं अपने आवेदन में सॉर्टिंग करता हूं। अभी मैं स्क्रिप्ट फ़ील्ड का परीक्षण कर रहा हूं। यह मूल रूप से यह एक टेम्पलेट (% s की जाँच करें) है कि मैं इस

sortScript = String.format(EDIT_DISTANCE_GROOVY_FUNC, fullname, FULLNAME_FIELD_NAME); 

समस्या यह http://code972.com/blog/2015/03/84-elasticsearch-one-tip-a-day-avoid-costly-scripts-at-all-costs है की तरह अपने आवेदन में भरने है स्क्रिप्ट

import org.elasticsearch.common.logging.*; 
ESLogger logger = ESLoggerFactory.getLogger('levenshtein_script'); 

def str1 = '%s'.split(' ').sort().join(' '); 
def str2 = doc['%s'].values.join(' '); //Needed since the field is analyzed. This will change when I reindex the data. 
def dist = new int[str1.size() + 1][str2.size() + 1] 
(0..str1.size()).each { dist[it][0] = it } 
(0..str2.size()).each { dist[0][it] = it } 
(1..str1.size()).each { i -> 
    (1..str2.size()).each { j -> 
     dist[i][j] = [dist[i - 1][j] + 1, dist[i][j - 1] + 1, dist[i - 1][j - 1] + ((str1[i - 1] == str2[j - 1]) ? 0 : 1)].min() 
    } 
} 
def result = dist[str1.size()][str2.size()] 
logger.info('Query param: ['+str1+'] | Term: ['+str2+'] | Result: ['+result+']'); 
return result; 

है। जो समझ में आता है।

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

मैं एक सेवा के रूप में ElasticSearch 1.7.5 का उपयोग कर रहा हूं। इसलिए देशी प्लगइन्स पहला समाधान नहीं होना चाहिए (मुझे यह पता नहीं है कि यह संभव है, मुझे अपने प्रदाता से जांच करनी होगी, लेकिन अगर यह एकमात्र व्यवहार्य समाधान है तो मैं बस यही करूँगा)।

अद्यतन

तो ऐसा लगता है एक अच्छा समाधान config/scripts फ़ोल्डर में बचाने के लिए होगा के रूप में यह एक बार https://www.elastic.co/blog/running-groovy-scripts-without-dynamic-scripting संकलित किया जाएगा। https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting.html को सहेजने के बजाय स्क्रिप्ट को अनुक्रमित किया जा सकता है। यह मेरे उपयोग के मामले के लिए और अधिक सुविधाजनक है। क्या स्क्रिप्ट के संकलन के संबंध में यह वही व्यवहार है? क्या इसे केवल एक बार संकलित किया जाएगा?

+1

यदि लेवेनशेटिन दूरी से परिणामों को क्रमबद्ध करने की एकमात्र आवश्यकता है, तो आप अपनी क्वेरी को फ़ज़ी खोज में बदल सकते हैं। https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-fuzzy-query.html। यह डिफ़ॉल्ट रूप से डैमरौ-लेवेनशेटिन का उपयोग करता है, लेकिन – jay

+0

को जिज्ञासा से सेट करके क्लासिक लेवेनशेटिन पर स्विच किया जा सकता है, जब आप कहते हैं कि आप अपने एप्लिकेशन से ओवरहेड को हटाना चाहते हैं - क्या यह धीमा है? या आप अपने आवेदन कोड में अतिरिक्त खोज तर्क नहीं चाहते हैं? – jay

+0

किसी भी तरह से मेरी पहली टिप्पणी समाप्त होने से पहले पोस्ट की गई थी - आप इसे गलत करने के लिए पारदर्शिता सेट करके क्लासिक लेवेनशेटिन पर सेट कर सकते हैं। यहां अधिक जानकारी: प्रतिक्रिया के लिए https://www.elastic.co/blog/found-fuzzy-search – jay

उत्तर

3

यह ध्यान रखना महत्वपूर्ण है कि ग्रोवी को लोचदार खोज 5.x में बहिष्कृत किया गया है और इसे एलैस्टिकसेर्च 6.0 में हटा दिया जाएगा। आप या तो इस कार्यक्षमता को बदलने के लिए पीले रंग की स्क्रिप्टिंग का उपयोग करना चाहते हैं या एक मूल जावा स्क्रिप्ट बनाएं जो संभवतः आपके लिए ऐसा करने के लिए लुसेन के LuceneLevenshteinDistance का उपयोग करे।

आपकी स्क्रिप्ट भी बहुत डरावनी है कि इसमें कई लूप (ज्यादातर ग्रोवी हेल्पर्स द्वारा छिपी हुई) और संभावित मिश्रण में बड़ी मेमोरी आवंटन जोड़ती है। मुझे पैमाने पर इसके प्रदर्शन के बारे में गंभीर संदेह है।

मैंने स्क्रिप्ट में %s की उपस्थिति को भी देखा, जिसका मुझे लगता है कि आपका स्वयं का कोड फ़ील्ड नाम को गतिशील रूप से बदल देता है। इस उद्देश्य के लिए आपको हमेशाparams का उपयोग करना चाहिए, फिर स्क्रिप्ट में चर के रूप में पैरामीटर का उपयोग करें। यह फ़ील्ड नाम प्रति स्क्रिप्ट के संस्करण को संकलित करने से बचाता है। (मुझे उम्मीद है कि आपको इसे फ़ाइल-आधारित बनाने के लिए ऐसा करना होगा)

क्या स्क्रिप्ट के संकलन के संबंध में यह वही व्यवहार है?

हां, फ़ाइल-आधारित स्क्रिप्ट सबसे सुरक्षित हैं (क्योंकि उन्हें मशीन को इंस्टॉल करने की आवश्यकता होती है)। फ़ाइल-आधारित स्क्रिप्ट संकलित की जाती हैं, बस इनलाइन और इंडेक्स-आधारित स्क्रिप्ट की तरह।

फ़ाइल-आधारित स्क्रिप्ट का नकारात्मक पक्ष यह है कि आपको उन्हें प्रत्येक नोड में जोड़ने की आवश्यकता है। उस पर नहीं, लेकिन प्रत्येक नोड को स्क्रिप्ट के समान संस्करण की आवश्यकता होती है।इसका अर्थ यह है कि, यदि आपने कभी इसे अपडेट करना चुना है, तो को एक नई स्क्रिप्ट जोड़ें और इसे प्रतिस्थापित करने के बजाय संदर्भित करें।

File-based scripts are picked up every 60 seconds by default

क्या इसे केवल एक बार संकलित किया जाएगा?

हाँ, प्रति नोड।

संबंधित मुद्दे