1. 程式人生 > >ElasticSearch之高亮顯示

ElasticSearch之高亮顯示

一 什麼是highlight

Highlight就是我們所謂的高亮,即允許對一個或者對個欄位在搜尋結果中高亮顯示。比如字型加粗或者字型呈現和其他文字普通顏色等。

為了執行高亮顯示,該欄位必須有實際的內容,並且這個欄位必須儲存,即在mapping中store設為true,不能只存在於記憶體中,否則系統會自動載入_source欄位並匹配相關的列。

二 三種高亮型別

ES提供了三種高亮型別,Lucene的plain highlighter,以及fast vector highlighter(fvh)以及posting highlighter.


2.1 Plain Highlighter

Plain Hightlighter是預設的高亮選擇,由使用Lucene Hightlighter實現的。它主要是試圖反應查詢匹配邏輯。

如果你想高亮很多欄位,而且帶有複雜的查詢,那麼這個highlight不是很快的。為了準確地反映查詢邏輯,它建立了一個很小的記憶體索引。

並通過Lucene的查詢執行計劃來重新執行原始的查詢條件,從而獲得對當前文件的低階匹配資訊,每個欄位和每個需要高亮顯示的文件都會重複這個過程,所以是有效能隱患的。所以需要你換一個hightlight型別

POST /ecommerce/music/_search

{

   "query":{

       "match":{"desc":"雅馬哈 "}

    },

   "highlight": {

       "fields": {

           "desc":{}

        }

    }

}

2.2 Fast Vector Highlighter

如果我們在mapping中對欄位指定了term_vector引數,且引數值是with_positions_offsets,那麼fast vector highlighter 將會替代plain highlighter成為預設的highlight型別。

它的主要特點:

# 快,特別是對於大欄位來說比較快(>1M)

# 要求在mapping中設定term_vector=with_positions_offsets

# 可以分配不同的權重來匹配不同的位置

# 我們可以設定一些屬性,boundary_chars,boundary_max_scan

fragment_offset

boundary_chars:分割字元,比如有些字元包含.,!?等特殊符號,我們可以指定是否遇到他們進行分割

boundary_max_scan:表示最多掃描多少個字元

fragment_offset:從什麼地方開始進行fragment

phrase_limit: 可以阻止對很多短語進行分詞從而吃掉很多記憶體,預設是256. 只有前256個phrase才會被考慮

PUT /blogs

{

 "mappings": {

   "news": {

     "properties": {

       "title": {

         "type": "text",

         "analyzer": "ik_max_word"

        },

       "content": {

         "type": "text",

         "analyzer": "ik_max_word",

         "term_vector" : "with_positions_offsets"

        }

      }

    }

  }

}

2.3 Posting Highlighter

如果我們在mapping裡index_options設定成offsets,這個posting hightlighter將會代替plain highlighter

它有哪些特點呢?

# 比起plain highlight效能更快一點,因為它不需要重新分析文件:尤其是對大檔案對效能的提高更為明顯

# 佔用更少的磁碟空間

# 把高亮顯示和句子分開,方便閱讀

# 使用BM25演算法,使搜尋的時候像是整篇文件

首先你在mapping需要預先定義:

PUT /website

{

   "mappings": {

       "article":{

           "properties": {

               "title":{

                   "type":"text"

               },

               "content":{

                   "type":"text",

                   "index_options": "offsets"

               }

            }

        }

    }

}

然後新增一條資料:

PUT /website/article/1

{

   "title":"Posting Highlighter",

   "content":"Note that the postings highlighter is meant toperform simple query terms highlighting, regardless of their positions."

}

高亮查詢

POST /website/article/_search

{

   "query":{

       "match":{"content":"Highlighter"}

    },

   "highlight": {

       "fields": {

            "content":{}

        }

    }

}


請注意:postinghighlighter只是做一個簡單的查詢,而不會管它的位置,這也就是說也短語查詢結合的時候,它會高亮顯示所有term,而不管它是否查詢匹配的一部分

POST /website/article/_search

{

   "query": {

       "match_phrase": {

          "content": {

              "query": "perform terms",

              "slop":3

           }

        }

    },

   "highlight": {

       "fields": {

           "content":{}

        }

    }

}

還有,postinghighlighter不支援很複雜的查詢,比如match_phrase_prefix,返回結果不會高亮

所以我們需要從實際情況去考慮,一般情況下,用plain highlight也就足夠了,不需要做其他額外的設定;如果對高亮的效能要求很高,可以嘗試啟用posting highlight;如果field的值特別大,超過了1M,那麼可以用fastvector highlight

三 控制引數

3.1設定高亮html標籤,預設是<em>標籤

我們可以使用pre_tags屬性和post_tags屬性自定義高亮顯示html標籤,去替代預設的em標籤

PUT /blogs

{

 "mappings": {

   "news": {

     "properties": {

       "title": {

         "type": "text",

         "analyzer": "ik_max_word"

        },

       "content": {

         "type": "text",

         "analyzer": "ik_max_word",

         "term_vector" : "with_positions_offsets"

        }

      }

    }

  }

}

PUT /blogs/news/1

{

   "title":"資本催熟的!流行!,或是共享經濟大潮裡的#流星#",

   "content":"迷你.KTV一開始就綁著/共享娛樂/的名號,和自助健身屋、自助咖啡廳、共享單車"

}

POST /blogs/news/_search

{

   "query": {

       "match":{"content":"迷你"}

    },

    "highlight": {

       "pre_tags": ["<h1>"],

       "post_tags": ["</h1>"],

       "fields": {

           "content":{}

        }

     }

}

3.2 強制使用某種highlight

當前你可能已經在mapping中設定了index_options選項為offsets或者設定了term_vector為with_positions_offsets,那麼他們預設的高亮就不是plain highlight,如果我們就希望使用plain highlight,那麼我們可以使用type引數來指定。他有三種可以選擇的型別:plain,posting,fvh.

POST /blogs/news/_search

{

   "query": {

       "match":{"content":"迷你"}

    },

    "highlight": {

       "fields": {

           "content":{

               "type":"plain"

            }

        }

     }

}

3.3高亮片段fragment的設定

fragment_size: 某欄位的值,長度是1萬,但是我們一般不會在頁面展示這麼長,可能只是展示一部分。設定要顯示出來的fragment文字判斷的長度,預設是100

number_of_fragments:高亮的文字片段有多個,你希望展示幾個

no_match_size: 可能沒有高亮的文字片段,這個引數可以設定從該欄位的開始制定長度為多少,然後作為預設的顯示

POST /blogs/news/_search

{

   "query": {

       "match":{"content":"自助"}

    },

    "highlight": {

       "fields": {

           "content":{

               "fragment_size" : 2,

               "number_of_fragments" : 1,

               "no_match_size": 2

            }

        }

     }

}

四 全域性設定

我們可以進行全域性的設定高亮屬性,然後fields欄位可以重寫這些全域性設定

GET /_search

{

   "query" : {

       "match": { "user": "kimchy" }

    },

   "highlight" : {

       "number_of_fragments" : 3,

       "fragment_size" : 150,

       "fields" : {

           "_all" : { "pre_tags" : ["<em>"],"post_tags" : ["</em>"] },

           "bio.title" : { "number_of_fragments" : 0 },

           "bio.author" : { "number_of_fragments" : 0 },

           "bio.content" : { "number_of_fragments" : 5,"order" : "score" }

        }

    }

}