2015-05-28 12 views
11

क्या लोचदार खोज विश्लेषण क्षेत्रों पर सटीक मिलान की पहचान करने का कोई तरीका है? आदर्श रूप से, मैं लोअरकेस, टोकननाइज़, स्टेम और शायद मेरे दस्तावेज़ों को ध्वन्यात्मक बनाना चाहता हूं, फिर प्रश्नों को "सटीक" मैचों को खींचने के लिए है।लोचदार खोज विश्लेषित क्षेत्रों पर सटीक मिलान

मेरा मतलब यह है कि अगर मैं "हैम्बर्गर बन्स" और "हैम्बर्गर" इंडेक्स करता हूं, तो उनका विश्लेषण ["हैमबर्गर", "बुन"] और ["हैमबर्गर"] के रूप में किया जाएगा। अगर मैं "हैम्बर्गर" की खोज करता हूं, तो यह केवल "हैम्बर्गर" दस्तावेज़ लौटाएगा, क्योंकि यह "सटीक" मैच है।

मैंने कीवर्ड टोकननाइज़र का उपयोग करने का प्रयास किया है, लेकिन यह व्यक्तिगत टोकन नहीं लगाएगा। क्या मुझे यह सुनिश्चित करने के लिए कुछ करने की ज़रूरत है कि टोकन की संख्या बराबर या तो हो?

मैं बहु-क्षेत्रों से परिचित हूं और "not_analyzed" प्रकार का उपयोग कर रहा हूं, लेकिन यह मेरी तुलना में अधिक प्रतिबंधित है। मैं सटीक मिलान, पोस्ट-विश्लेषण करना चाहता हूं।

उत्तर

9

शिंगल टोकननाइज़र का उपयोग स्टेमिंग और जो भी आपको चाहिए, के साथ एक साथ करें। token_count प्रकार का उप-क्षेत्र जोड़ें जो फ़ील्ड में टोकन की संख्या की गणना करेगा।

खोज समय पर, आपको खोज टेक्स्ट में मौजूद टोकन की संख्या के साथ इंडेक्स में टोकन की संख्या से मेल खाने के लिए एक अतिरिक्त फ़िल्टर जोड़ने की आवश्यकता है। जब आप वास्तविक खोज करते हैं, तो आपको एक अतिरिक्त चरण की आवश्यकता होगी, जो खोज स्ट्रिंग में टोकन को गिनना चाहिए। ऐसा इसलिए है क्योंकि शिंगल टोकन के एकाधिक क्रमपरिवर्तन बनाएंगे और आपको यह सुनिश्चित करना होगा कि यह आपके खोज टेक्स्ट के आकार से मेल खाता हो।

{ 
    "settings": { 
    "analysis": { 
     "filter": { 
     "filter_shingle": { 
      "type": "shingle", 
      "max_shingle_size": 10, 
      "min_shingle_size": 2, 
      "output_unigrams": true 
     }, 
     "filter_stemmer": { 
      "type": "porter_stem", 
      "language": "_english_" 
     } 
     }, 
     "analyzer": { 
     "ShingleAnalyzer": { 
      "tokenizer": "standard", 
      "filter": [ 
      "lowercase", 
      "snowball", 
      "filter_stemmer", 
      "filter_shingle" 
      ] 
     } 
     } 
    } 
    }, 
    "mappings": { 
    "test": { 
     "properties": { 
     "text": { 
      "type": "string", 
      "analyzer": "ShingleAnalyzer", 
      "fields": { 
      "word_count": { 
       "type": "token_count", 
       "store": "yes", 
       "analyzer": "ShingleAnalyzer" 
      } 
      } 
     } 
     } 
    } 
    } 
} 

और क्वेरी:

{ 
    "query": { 
    "filtered": { 
     "query": { 
     "match_phrase": { 
      "text": { 
      "query": "HaMbUrGeRs BUN" 
      } 
     } 
     }, 
     "filter": { 
     "term": { 
      "text.word_count": "2" 
     } 
     } 
    } 
    } 
} 

shingles फिल्टर यहां महत्वपूर्ण है क्योंकि यह टोकन के संयोजन बना सकते हैं

इस के लिए कोई प्रयास, केवल आपके जानकारी देने के लिए। और उससे भी अधिक, ये संयोजन हैं जो आदेश या टोकन रखते हैं। इमो, यहां पूरा करने के लिए सबसे कठिन आवश्यकता टोकन (स्टेमिंग, लोअरकेसिंग इत्यादि) को बदलने और मूल पाठ को वापस इकट्ठा करने के लिए भी है। जब तक आप अपना खुद का "concatenation" फ़िल्टर परिभाषित नहीं करते हैं, मुझे नहीं लगता कि shingles फ़िल्टर का उपयोग करने से कोई अन्य तरीका नहीं है।

लेकिन shingles के साथ एक और मुद्दा है: यह उन संयोजनों को बनाता है जिनकी आवश्यकता नहीं है।

  "angeles", 
      "buns", 
      "buns in", 
      "buns in los", 
      "buns in los angeles", 
      "hamburgers", 
      "hamburgers buns", 
      "hamburgers buns in", 
      "hamburgers buns in los", 
      "hamburgers buns in los angeles", 
      "in", 
      "in los", 
      "in los angeles", 
      "los", 
      "los angeles" 

आप केवल उन दस्तावेज़ों को बिल्कुल अर्थ से मेल खाते हैं में रुचि रखते हैं, दस्तावेजों के ऊपर केवल मेल खाता है आप के लिए "में हैम्बर्गर बन्स की खोज करते हैं: "Hamburgers buns in Los Angeles" की तरह एक पाठ के लिए आप दाद की एक लंबी सूची के साथ अंत लॉस एंजिल्स "(और लॉस एंजिल्स में किसी भी हैमबर्गर बन्स की तरह कुछ नहीं मिला है) तो आपको शिंगलों की उस लंबी सूची को फ़िल्टर करने के लिए एक तरीका चाहिए। जिस तरह से मैं इसे देखता हूं word_count का उपयोग करना है।

+0

शिंगलों का उद्देश्य क्या है? – abroekhof

+0

इसके अलावा, क्या पोर्टर और स्नोबॉल स्टेमर दोनों का उपयोग करने का कोई कारण है? – abroekhof

+0

कोई कारण नहीं। यह सिर्फ एक उदाहरण है जो मेरे पास था और कुछ वास्तविक कोड दिखाने के लिए इसे जल्दी से बदलने में सक्षम था। महत्वपूर्ण भाग 'shingle' फ़िल्टर, 'token_count' प्रकार फ़ील्ड और क्वेरी स्वयं हैं। शेष फ़िल्टर केवल उदाहरण हैं: उन्हें बाहर निकाला जा सकता है, अन्य सामान जोड़ा गया है। –

3

आप उस उद्देश्य के लिए multi-fields उपयोग करें और अपनी analyzed क्षेत्र के भीतर एक not_analyzed उप क्षेत्र हो सकता है (यह इस उदाहरण में item कॉल)।

{ 
    "yourtype": { 
    "properties": { 
     "item": { 
     "type": "string", 
     "fields": { 
      "raw": { 
      "type": "string", 
      "index": "not_analyzed" 
      } 
     } 
     } 
    } 
    } 
} 
मानचित्रण के इस प्रकार के साथ

है, तो आप देख सकते हैं कि मान Hamburgers और Hamburger Buns में से प्रत्येक के अपने बहु क्षेत्र item और item.raw करने के लिए "देखी" कर रहे हैं सम्मान के साथ विश्लेषक द्वारा: अपने मानचित्रण इस तरह दिखना करना होगा

Hamburger के लिए:

curl -XGET 'localhost:9200/yourtypes/_analyze?field=item&pretty' -d 'Hamburger' 
{ 
    "tokens" : [ { 
    "token" : "hamburger", 
    "start_offset" : 0, 
    "end_offset" : 10, 
    "type" : "<ALPHANUM>", 
    "position" : 1 
    } ] 
} 
curl -XGET 'localhost:9200/yourtypes/_analyze?field=item.raw&pretty' -d 'Hamburger' 
{ 
    "tokens" : [ { 
    "token" : "Hamburger", 
    "start_offset" : 0, 
    "end_offset" : 10, 
    "type" : "word", 
    "position" : 1 
    } ] 
} 

Hamburger Buns के लिए:

curl -XGET 'localhost:9200/yourtypes/_analyze?field=item&pretty' -d 'Hamburger Buns' 
{ 
    "tokens" : [ { 
    "token" : "hamburger", 
    "start_offset" : 0, 
    "end_offset" : 10, 
    "type" : "<ALPHANUM>", 
    "position" : 1 
    }, { 
    "token" : "buns", 
    "start_offset" : 11, 
    "end_offset" : 15, 
    "type" : "<ALPHANUM>", 
    "position" : 2 
    } ] 
} 
curl -XGET 'localhost:9200/yourtypes/_analyze?field=item.raw&pretty' -d 'Hamburger Buns' 
{ 
    "tokens" : [ { 
    "token" : "Hamburger Buns", 
    "start_offset" : 0, 
    "end_offset" : 15, 
    "type" : "word", 
    "position" : 1 
    } ] 
} 

जैसा कि आप देख सकते हैं, not_analyzed फ़ील्ड को इनपुट के रूप में ठीक से अनुक्रमित किया जा रहा है।

अब, चलो सूचकांक दो नमूना दस्तावेजों इस वर्णन करने के लिए:

curl -XPOST localhost:9200/yourtypes/_bulk -d ' 
{"index": {"_type": "yourtype", "_id": 1}} 
{"item": "Hamburger"} 
{"index": {"_type": "yourtype", "_id": 2}} 
{"item": "Hamburger Buns"} 
' 

और अंत में, अपने सवाल का जवाब देने, अगर आप Hamburger का सटीक मिलान करना चाहते हैं, तो आप अपने उप-क्षेत्र item.raw भीतर खोज कर सकते इस तरह (ध्यान दें कि अगर मैच के लिए भी है):

curl -XPOST localhost:9200/yourtypes/yourtype/_search -d '{ 
    "query": { 
    "term": { 
     "item.raw": "Hamburger" 
    } 
    } 
}' 

और आप प्राप्त करेंगे:

{ 
    ... 
    "hits" : { 
    "total" : 1, 
    "max_score" : 0.30685282, 
    "hits" : [ { 
     "_index" : "yourtypes", 
     "_type" : "yourtype", 
     "_id" : "1", 
     "_score" : 0.30685282, 
     "_source":{"item": "Hamburger"} 
    } ] 
    } 
} 

अद्यतन (देखें टिप्पणी/नीचे चर्चा और सवाल फिर से संपादित करें)

टिप्पणियों से अपने उदाहरण ले रहा है और HaMbUrGeR BuNs मैच Hamburger buns आप बस एक match क्वेरी इस तरह से इसे प्राप्त कर सकता है की कोशिश कर रहा।

curl -XPOST localhost:9200/yourtypes/yourtype/_search?pretty -d '{ 
    "query": { 
    "match": { 
     "item": { 
     "query": "HaMbUrGeR BuNs", 
     "operator": "and" 
     } 
    } 
    } 
}' 

ही दो अनुक्रमित दस्तावेज़ के आधार पर कौन सा ऊपर निकलेगा

{ 
    ... 
    "hits" : { 
    "total" : 1, 
    "max_score" : 0.2712221, 
    "hits" : [ { 
     "_index" : "yourtypes", 
     "_type" : "yourtype", 
     "_id" : "2", 
     "_score" : 0.2712221, 
     "_source":{"item": "Hamburger Buns"} 
    } ] 
    } 
} 
+1

अरे, इस उत्तर में आपके द्वारा दिए गए समय के लिए धन्यवाद, दुर्भाग्य से यह मेरे प्रश्न का उत्तर नहीं देता है। मैं समझता हूं कि यदि मैं not_analyzed फ़ील्ड में सटीक शब्द की खोज करता हूं, तो यह सही परिणाम देगा, लेकिन मैं अधिक लचीलापन ढूंढ रहा हूं। उदाहरण के लिए, मैं इसे "हैम्बर्गर बन्स" वापस लौटना चाहता हूं, यदि मैं "हामबर्गेरस बुन" खोजता हूं, जो "not_analyzed" नहीं करेगा। विश्लेषण के बाद, यह "सटीक" परिणाम है, जैसा कि वे मेल खाते हैं। इसका कोई मतलब भी है क्या? – abroekhof

+0

हां, यह समझ में आता है। क्षमा करें अगर मैंने आपके प्रश्न को गलत समझा। हालांकि, आपको अपना प्रश्न अपडेट करना चाहिए और उल्लेख करना चाहिए कि आप बहु फ़ील्ड के बारे में जानते हैं और यह वह नहीं है जिसे आप ढूंढ रहे हैं। – Val

+0

आपके इनपुट के लिए फिर से धन्यवाद, मैं इसकी सराहना करता हूं। – abroekhof

4

आप आप क्या अपेक्षा के अनुरूप विश्लेषक रख सकते (लोअरकेस, tokenize, तना, ...), और query_string का उपयोग मुख्य क्वेरी के रूप में करें, match_phrase खोज करने के लिए बढ़ती क्वेरी के रूप में। कुछ इस तरह:

{ 
    "bool" : { 
     "should" : [ 
     { 
      "query_string" : { 
       "default_field" : "your_field", 
       "default_operator" : "OR", 
       "phrase_slop" : 1, 
       "query" : "Hamburger" 
      } 
     }, 
     { 
      "match_phrase": { 
       "your_field": { 
        "query": "Hamburger" 
       } 
      } 
     } 
     ] 
    } 
} 

यह दोनों दस्तावेज़ से मेल होगा, और सटीक मिलान (match_phrase) क्वेरी के मैच के बाद शीर्ष पर होगा दोनों should खंड (और अधिक अंक प्राप्त)

default_operator या के लिए सेट है, यह "हैम्बर्गर बन्स" (hamburger या bun) से पूछताछ में मदद करेगा) दस्तावेज़ "हैम्बर्गर" से भी मेल खाता है। phrase_slop केवल दूरी = 1 के साथ शर्तों से मेल खाने के लिए 1 पर सेट है, उदा। Hamburger Buns के लिए खोज दस्तावेज़ Hamburger Big Buns से मेल नहीं खाएगा। आप इसे अपनी आवश्यकताओं पर निर्भर कर सकते हैं।

अधिक जानकारी के लिए आप Closer is better, Query string देख सकते हैं।

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