2017-10-24 22 views
5

से मैं एक ElasticSearch सूचकांक कि कुछ इस तरह दिखता है dog के लिए, मुझे पहले और तीसरे दस्तावेज मिलते हैं, जैसा कि मैं उम्मीद करता हूं। और मैं खोज दस्तावेजों को जिस तरह से पसंद करता हूं वज़न कर सकता हूं (असल में, मैं इस प्रश्न के लिए अप्रासंगिक फ़ील्ड के समूह पर वजन के लिए function_score क्वेरी का उपयोग कर रहा हूं)।क्रमबद्ध कीवर्ड क्षेत्र सरणी प्रासंगिकता

क्या मैं करने के लिए की तरह चाहते तरह tags क्षेत्र इतना है कि सबसे अधिक प्रासंगिक टैग स्वयं दस्तावेज़ का सॉर्ट क्रम को प्रभावित किए बिना, पहले लौटा दिए जाते हैं है। तो मैं इस तरह एक परिणाम के लिए आशा करती हूं कि:

{ "title": "Something about Dog Food", "tags": ["dogs", "dogfood", "articles"] } 

इसके बजाय अब मैं क्या मिल की:

{ "title": "Something about Dog Food", "tags": ["articles", "dogs", "dogfood"] } 

प्रलेखन sort पर और function score मेरे मामले को कवर नहीं है। किसी भी मदद की सराहना की। धन्यवाद!

+0

ईएस का कौन सा संस्करण यह है, क्योंकि आप '" टाइप ":" स्ट्रिंग "का उपयोग कर रहे हैं? –

+0

@AndreiStefan 5.5.0 –

+0

का उपयोग करके आपको 'टेक्स्ट' /' कीवर्ड 'फ़ील्ड में जाने पर विचार करना चाहिए। 'स्ट्रिंग' [5.x में बहिष्कृत और 6.0 में हटा दी गई हैं] (https://github.com/elastic/elasticsearch/pull/16877)। –

उत्तर

2

आपको एक खोज कॉल से क्या मिलता है स्रोत दस्तावेज हैं। प्रतिक्रिया में दस्तावेज़ ठीक उसी रूप में लौटाए जाते हैं जब आपने उन्हें अनुक्रमित किया था, जिसका अर्थ है कि यदि आपने ["articles", "dogs", "dogfood"] को अनुक्रमित किया है, तो आप हमेशा उस सरणी को उस अनारक्षित रूप में प्राप्त करेंगे।

इस पर जाने का एक तरीका script_field घोषित करना है जो आपकी सरणी को सॉर्ट करने और उस प्रकार के परिणाम को वापस करने के लिए एक छोटी सी स्क्रिप्ट लागू करता है।

क्या स्क्रिप्ट है करता है बस शब्दों सूची

{ 
    "_source": ["title"], 
    "query" : { 
     "match_all": {} 
    }, 
    "script_fields" : { 
     "sorted_tags" : { 
      "script" : { 
       "lang": "painless", 
       "source": "return params._source.tags.stream().sorted((i1, i2) -> i1.indexOf(params.search) > -1 ? -1 : 1).collect(Collectors.toList())", 
       "params" : { 
        "search": "dog" 
       } 
      } 
     } 
    } 
} 

यह कुछ इस तरह वापस आ जाएगी, जैसा कि आप sorted_tags श्रेणी भी देख सकते के सामने खोज पद शामिल ले जाने के रूप में आप शब्द ही शामिल हों उम्मीद करते हैं।

{ 
    "took": 18, 
    "timed_out": false, 
    "_shards": { 
    "total": 5, 
    "successful": 5, 
    "skipped": 0, 
    "failed": 0 
    }, 
    "hits": { 
    "total": 1, 
    "max_score": 1, 
    "hits": [ 
     { 
     "_index": "tests", 
     "_type": "article", 
     "_id": "1", 
     "_score": 1, 
     "_source": { 
      "title": "Something about Dog Food" 
     }, 
     "fields": { 
      "sorted_tags": [ 
      "dogfood", 
      "dogs", 
      "articles" 
      ] 
     } 
     } 
    ] 
    } 
} 
5

आप _source अपने "मिलान" क्षमता को देखते हुए दस्तावेजों की (अपने टैग की सरणी) क्रमबद्ध नहीं कर सकते। ऐसा करने का एक तरीका नेस्टेड फ़ील्ड और inner_hits का उपयोग करके है जो आपको मिलान किए गए नेस्टेड फ़ील्ड को सॉर्ट करने की अनुमति देता है।

मेरे सुझाव एक nested क्षेत्र में अपनी tags को बदलने के लिए है (मैं सिर्फ सादगी से वहाँ keyword चुना है, लेकिन आप भी text हो सकता है और अपनी पसंद के विश्लेषक):

PUT test 
{ 
    "mappings": { 
    "article": { 
     "properties": { 
     "title": { 
      "type": "string" 
     }, 
     "tags": { 
      "type": "nested", 
      "properties": { 
      "value": { 
       "type": "keyword" 
      } 
      } 
     } 
     } 
    } 
    } 
} 

और इस तरह का उपयोग करें क्वेरी:

GET test/_search 
{ 
    "_source": { 
    "exclude": "tags" 
    }, 
    "query": { 
    "bool": { 
     "must": [ 
     { 
      "match": { 
      "title": "dogs" 
      } 
     }, 
     { 
      "nested": { 
      "path": "tags", 
      "query": { 
       "bool": { 
       "should": [ 
        { 
        "match_all": {} 
        }, 
        { 
        "match": { 
         "tags.value": "dogs" 
        } 
        } 
       ] 
       } 
      }, 
      "inner_hits": { 
       "sort": { 
       "_score": "desc" 
       } 
      } 
      } 
     } 
     ] 
    } 
    } 
} 

आप कहाँ एक ही पाठ आप शीर्षक पर मिलान करने का प्रयास के लिए टैग नेस्ट क्षेत्र मूल्य पर मैच के लिए प्रयास करें। फिर, inner_hits सॉर्टिंग का उपयोग करके, आप वास्तव में नेस्टेड मानों को उनके आंतरिक स्कोरिंग के आधार पर सॉर्ट कर सकते हैं।

@ वैल का सुझाव बहुत अच्छा है, लेकिन यह तब तक अच्छा है जब तक आपके "प्रासंगिक टैग" के लिए आप एक साधारण पाठ मिलान के साथ ठीक नहीं हैं (i1.indexOf(params.search))। उनके समाधान का सबसे बड़ा फायदा यह है कि आपको मानचित्रण को बदलने की जरूरत नहीं है।

मेरा समाधान का बड़ा फायदा यह है कि आप वास्तव में "प्रासंगिक" टैग निर्धारित करने के लिए Elasticsearch वास्तविक खोज क्षमताओं का उपयोग कर रहे हैं। लेकिन दोष यह है कि आपको नियमित सरल keyword के बजाय nested फ़ील्ड की आवश्यकता है।

+0

सामान्य आंद्रेई के रूप में महान नौकरी, मैं 'inner_hits' सॉर्टिंग के साथ एक अद्यतन प्रदान करने की सोच रहा था, लेकिन खुशी है कि आपने इसे किया ;-) – Val

+0

यह वास्तव में एक अच्छा दृष्टिकोण की तरह लगता है। एसक्यूएल सबक्वायरी के समान इस प्रदर्शन का प्रदर्शन है? –

+0

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

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