ElasticSearch वाले शब्द के एक भाग की खोज कैसे करें


128

मैंने हाल ही में ElasticSearch का उपयोग शुरू किया है और मैं इसे किसी शब्द के एक भाग के लिए खोज करने के लिए प्रतीत नहीं कर सकता।

उदाहरण: मेरे पास ElasticSearch में अनुक्रमित मेरे couchdb से तीन दस्तावेज़ हैं:

{
  "_id" : "1",
  "name" : "John Doeman",
  "function" : "Janitor"
}
{
  "_id" : "2",
  "name" : "Jane Doewoman",
  "function" : "Teacher"
}
{
  "_id" : "3",
  "name" : "Jimmy Jackal",
  "function" : "Student"
} 

तो अब, मैं "डो" वाले सभी दस्तावेजों की खोज करना चाहता हूं

curl http://localhost:9200/my_idx/my_type/_search?q=Doe

यह कोई हिट नहीं है। लेकिन अगर मैं खोजता हूं

curl http://localhost:9200/my_idx/my_type/_search?q=Doeman

यह एक दस्तावेज़ (जॉन Doeman) लौटाता है।

मैंने अपने इंडेक्स के गुणों के रूप में अलग-अलग एनालाइज़र और अलग-अलग फ़िल्टर सेट करने की कोशिश की है। मैंने एक पूर्ण विकसित क्वेरी का उपयोग करने की भी कोशिश की है (उदाहरण के लिए:

{
  "query": {
    "term": {
      "name": "Doe"
    }
  }
}

) लेकिन काम करने के लिए कुछ भी नहीं लगता है।

जब मैं "डो" खोजता हूं, तो मैं जॉन डोमेन और जेन डूमोमैन दोनों को कैसे ढूंढ सकता हूं?

अपडेट करें

मैंने nGram टोकन और फिल्टर का उपयोग करने की कोशिश की, जैसे कि इगोर ने इस तरह का प्रस्ताव दिया:

{
  "index": {
    "index": "my_idx",
    "type": "my_type",
    "bulk_size": "100",
    "bulk_timeout": "10ms",
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "type": "custom",
          "tokenizer": "my_ngram_tokenizer",
          "filter": [
            "my_ngram_filter"
          ]
        }
      },
      "filter": {
        "my_ngram_filter": {
          "type": "nGram",
          "min_gram": 1,
          "max_gram": 1
        }
      },
      "tokenizer": {
        "my_ngram_tokenizer": {
          "type": "nGram",
          "min_gram": 1,
          "max_gram": 1
        }
      }
    }
  }
}

अब मेरे पास जो समस्या है वह यह है कि प्रत्येक और प्रत्येक क्वेरी सभी दस्तावेज़ लौटाता है। कोई संकेत? NGram का उपयोग करने पर ElasticSearch प्रलेखन महान नहीं है ...


9
कोई आश्चर्य नहीं, आप 1 मिनट के लिए मिनट / अधिकतम एनजी सेट habe, तो 1 पत्र :)
मार्टिन बी

जवाबों:


85

मैं भी nGram का उपयोग कर रहा हूँ। मैं एक फिल्टर के रूप में मानक टोकन और nGram का उपयोग करता हूं। यहाँ मेरा सेटअप है:

{
  "index": {
    "index": "my_idx",
    "type": "my_type",
    "analysis": {
      "index_analyzer": {
        "my_index_analyzer": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "mynGram"
          ]
        }
      },
      "search_analyzer": {
        "my_search_analyzer": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "standard",
            "lowercase",
            "mynGram"
          ]
        }
      },
      "filter": {
        "mynGram": {
          "type": "nGram",
          "min_gram": 2,
          "max_gram": 50
        }
      }
    }
  }
}

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



क्या वह है जो आपको सूचकांक की सेटिंग्स से मिलता है या यह है कि आप इसे कॉन्फ़िगर करने के लिए इलास्टिसर्च में क्या पोस्ट करते हैं?
टॉमस जानसन

यह एलिस्टिक्स खोज को कॉन्फ़िगर करने के लिए एक पोस्ट है।
रोका

: मैं Elasticsearch के वर्तमान संस्करण के साथ फर्म नहीं कर रहा हूँ, लेकिन डॉक्स में यह उल्लेख करना चाहिए elastic.co/guide/en/elasticsearch/reference/current/index.html
Roka

1
@JimC मैंने कम से कम 7 वर्षों के लिए ElasticSearch का उपयोग नहीं किया है, इसलिए मुझे परियोजना के वर्तमान परिवर्तनों की जानकारी नहीं है।
Roka

63

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


14
इगोर सही कह रहे हैं। कम से कम अग्रणी * को हटा दें। : NGram ElasticSearch उदाहरण के लिए, इस सार को देखने gist.github.com/988923
कर्मी

3
@ कर्मी: आपके संपूर्ण उदाहरण के लिए धन्यवाद! शायद आप अपनी टिप्पणी को एक वास्तविक उत्तर के रूप में जोड़ना चाहते हैं, यह वही है जो मेरे लिए काम कर रहा है और मैं क्या करना चाहूंगा।
फाबियन स्टीग

54

मुझे लगता है कि किसी भी मैपिंग को बदलने की कोई आवश्यकता नहीं है। Query_string का उपयोग करने का प्रयास करें , यह एकदम सही है। सभी परिदृश्य डिफ़ॉल्ट मानक विश्लेषक के साथ काम करेंगे:

हमारे पास डेटा है:

{"_id" : "1","name" : "John Doeman","function" : "Janitor"}
{"_id" : "2","name" : "Jane Doewoman","function" : "Teacher"}

दृष्टांत 1:

{"query": {
    "query_string" : {"default_field" : "name", "query" : "*Doe*"}
} }

उत्तर:

{"_id" : "1","name" : "John Doeman","function" : "Janitor"}
{"_id" : "2","name" : "Jane Doewoman","function" : "Teacher"}

परिदृश्य 2:

{"query": {
    "query_string" : {"default_field" : "name", "query" : "*Jan*"}
} }

उत्तर:

{"_id" : "1","name" : "John Doeman","function" : "Janitor"}

परिदृश्य 3:

{"query": {
    "query_string" : {"default_field" : "name", "query" : "*oh* *oe*"}
} }

उत्तर:

{"_id" : "1","name" : "John Doeman","function" : "Janitor"}
{"_id" : "2","name" : "Jane Doewoman","function" : "Teacher"}

EDIT - वसंत डेटा लोचदार खोज के साथ समान कार्यान्वयन https://stackoverflow.com/a/43579948/2357869 के

एक और स्पष्टीकरण कि कैसे क्वेरी_स्ट्रीमिंग दूसरों की तुलना में बेहतर है https://stackoverflow.com/a/43321606/2357869


3
मुझे लगता है कि यह सबसे आसान है
Esgi Dendyanri

हाँ । मैंने अपने प्रोजेक्ट में लागू किया है।
ओपस्टेर एलिटिक्सर्च प्रो-विजय

कैसे खोज करने के लिए कई क्षेत्रों को शामिल करें?
शुभम ए।

इसे आज़माएँ: - {"क्वेरी": {"query_string": {"फ़ील्ड्स": ["सामग्री", "नाम"], "क्वेरी": "यह और वह"}}}
ऑप्स्टर एलियस्टीसर्च प्रो-विजय


14

अपने अनुक्रमणिका मैपिंग को बदले बिना आप एक सरल उपसर्ग क्वेरी कर सकते हैं जो आंशिक खोज करेंगे जैसे आप उम्मीद कर रहे हैं

अर्थात।

{
  "query": { 
    "prefix" : { "name" : "Doe" }
  }
}

https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-prefix-query.html


क्या आप उपसर्ग क्वेरी का उपयोग करके बहु क्षेत्र खोज कर सकते हैं?
15 से 15

धन्यवाद, बस मैं क्या देख रहा था! प्रदर्शन प्रभाव पर कोई विचार?
Vingtoft

6

यहां वर्णित समाधान का प्रयास करें: ElasticSearch में सटीक पदार्थ खोजें

{
    "mappings": {
        "my_type": {
            "index_analyzer":"index_ngram",
            "search_analyzer":"search_ngram"
        }
    },
    "settings": {
        "analysis": {
            "filter": {
                "ngram_filter": {
                    "type": "ngram",
                    "min_gram": 3,
                    "max_gram": 8
                }
            },
            "analyzer": {
                "index_ngram": {
                    "type": "custom",
                    "tokenizer": "keyword",
                    "filter": [ "ngram_filter", "lowercase" ]
                },
                "search_ngram": {
                    "type": "custom",
                    "tokenizer": "keyword",
                    "filter": "lowercase"
                }
            }
        }
    }
}

डिस्क उपयोग की समस्या और बहुत लंबी खोज शब्द समस्या को हल करने के लिए छोटे 8 वर्णों के लंबे नगों का उपयोग किया जाता है (इसके साथ कॉन्फ़िगर किया गया: "max_gram": 8 )। 8 से अधिक वर्णों वाले शब्दों की खोज करने के लिए, अपनी खोज को एक बूलियन में बदल दें और उस स्ट्रिंग में प्रतिस्थापित प्रत्येक अलग-अलग 8-वर्ण की तलाश करें। उदाहरण के लिए, यदि कोई उपयोगकर्ता बड़े यार्ड (10-वर्ण स्ट्रिंग) के लिए खोज करता है, तो खोज होगी:

"अरे यार और आरजीई यार और आरजीई यार्ड


2
मृत लिंक, pls तय
DarkMukke

मैं कुछ समय से ऐसा ही कुछ देख रहा था। धन्यवाद! आप के साथ कैसे स्मृति तराजू पता है min_gramऔर max_gramऐसा लगता है जैसे कि यह रैखिक फ़ील्ड मानों का आकार और की सीमा पर निर्भर होगा minऔर max। कैसे कुछ इस तरह से उपयोग किया जाता है?
ग्लेन थॉम्पसन

यह भी कोई कारण है कि ngramएक टोकन पर एक फिल्टर है? क्या आप इसे एक टोकन के रूप में नहीं ले सकते हैं और फिर एक लोअरकेस फ़िल्टर लागू कर सकते हैं ... index_ngram: { type: "custom", tokenizer: "ngram_tokenizer", filter: [ "lowercase" ] }मैंने इसे आज़माया और एनालाइज़र टेस्ट एपीआई का उपयोग करके समान परिणाम देने के लिए लगता है
ग्लेन थॉम्पसन

2

यदि आप स्वत: पूर्ण कार्यक्षमता को लागू करना चाहते हैं, तो पूर्णता सुझाव सबसे साफ समाधान है। अगले ब्लॉग पोस्ट में बहुत स्पष्ट वर्णन है कि यह कैसे काम करता है।

दो शब्दों में, यह एक इन-मेमोरी डेटा संरचना है जिसे एफएसटी कहा जाता है जिसमें मान्य सुझाव होते हैं और यह तेजी से पुनर्प्राप्ति और मेमोरी उपयोग के लिए अनुकूलित होता है। अनिवार्य रूप से, यह सिर्फ एक ग्राफ है। उदाहरण के लिए, और FST शब्दों से युक्त के लिए hotel, marriot, mercure, munchenऔर munichइस प्रकार दिखाई देगा:

यहाँ छवि विवरण दर्ज करें


2

आप regexp का उपयोग कर सकते हैं।

{ "_id" : "1", "name" : "John Doeman" , "function" : "Janitor"}
{ "_id" : "2", "name" : "Jane Doewoman","function" : "Teacher"  }
{ "_id" : "3", "name" : "Jimmy Jackal" ,"function" : "Student"  } 

यदि आप इस क्वेरी का उपयोग करते हैं:

{
  "query": {
    "regexp": {
      "name": "J.*"
    }
  }
}

आप सभी डेटा देंगे कि उनका नाम "जे" से शुरू होता है। आप केवल पहले दो रिकॉर्ड प्राप्त करना चाहते हैं कि उनका नाम "आदमी" के साथ समाप्त होता है, इसलिए आप इस क्वेरी का उपयोग कर सकते हैं:

{
  "query": { 
    "regexp": {
      "name": ".*man"
    }
  }
}

और यदि आप सभी रिकॉर्ड प्राप्त करना चाहते हैं कि उनके नाम में "एम" मौजूद है, तो आप इस क्वेरी का उपयोग कर सकते हैं:

{
  "query": { 
    "regexp": {
      "name": ".*m.*"
    }
  }
}

यह मेरे लिए काम करता है। और मुझे आशा है कि मेरा जवाब आपकी समस्या को हल करने के लिए उपयुक्त होगा।


1

Wilcards (*) के उपयोग से स्कोर के कैल्क को रोका जा सकता है


1
क्या आप अपने उत्तर में अधिक विवरण जोड़ सकते हैं? यह क्या करता है पर प्रलेखन के लिए एक नमूना कोड या संदर्भ प्रदान करें।
क्रे

0

मैं इसका उपयोग कर रहा हूं और मुझे काम मिला है

"query": {
        "query_string" : {
            "query" : "*test*",
            "fields" : ["field1","field2"],
            "analyze_wildcard" : true,
            "allow_leading_wildcard": true
        }
    }

-6

कोई बात नहीं।

मुझे ल्यूसीन दस्तावेज को देखना था। लगता है मैं वाइल्डकार्ड का उपयोग कर सकता हूं! :-)

curl http://localhost:9200/my_idx/my_type/_search?q=*Doe*

उसने चाल चली!


11
@Imotov उत्तर देखें। वाइल्डकार्ड का उपयोग बिल्कुल भी अच्छा नहीं है।
माइक मुनरो

5
@Idx - देखें कि आपका स्वयं का उत्तर कैसे अस्वीकृत है। डाउनवोट्स एक उत्तर की गुणवत्ता और प्रासंगिकता का प्रतिनिधित्व करता है। क्या आप सही उत्तर को स्वीकार करने में एक मिनट का समय लगा सकते हैं? कम से कम नए उपयोगकर्ता आपके आभारी होंगे।
asyncwait

3
पर्याप्त गिरावट। ओपी ने स्पष्ट किया कि अब सबसे अच्छा जवाब क्या है। साझा करने के लिए +1 जो किसी को बेहतर पोस्ट करने से पहले सबसे अच्छा जवाब लगता है।
एस। डैनियल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.