Elasticsearch查詢——highlight(高亮顯示)

Highlighters 高亮顯示

日常生活中我們使用搜索工具嘗試查詢一些信息的時候,常常可以看到返回的結果集中和我們查詢條件相符合的字段被特殊的顏色所標記,這就是結果高亮顯示。通過高亮顯示用戶可以明顯的發現查詢匹配的位置,

ES使用highlight來實現搜索結果中一個或多個字段突出顯示。

高亮顯示需要字段中的內容,如果沒有存儲字段store=true,則加載實際的_source並從_source提取相關字段。

簡單的例子

下面是一個簡單的例子,使用的映射結構

PUT article/_mapping
{
    "properties": {
        "article_type": {
            "type": "keyword"
        },
        "article_title": {
            "type": "text"
        },
        "content": {
            "type": "text"
        },
        "date": {
            "type": "date",
            "format": ["yyyy-MM-dd HH:mm:ss"]
        },
        "read_num": {
            "type": "integer"
        },
        "comment_num": {
            "type": "integer"
        }
    }
}

數據內容就是本人的博客信息

{"index":{"_index":"article","_id":0}}
{"article_type": "原創","article_title": "Elasticsearch查詢——Profile API(性能分析)","content": "Profile API 性能分析 平時開發的過程中我們可能需要對一些查詢操作進行優化,而優化之前的工作就是要對操作的性能進行分析,而ES提供了Profile API來幫助用戶進行性能分析。它讓用戶瞭解如何在較低的級別執行搜索請求,這樣用戶就可以理解爲什麼某些請求比較慢,並採取措施改進它們。","date": "2019-12-22 22:22:29","read_num": 4,"comment_num": 0}
{"index":{"_index":"article","_id":1}}
{"article_type": "原創","article_title": "Elasticsearch查詢——Search Template(模板查詢)","content": "關於版本 內容 版本 Elasticsearch版本 7.2.0 ES模板搜索——Search Template 日常開發中我們可能需要頻繁的使用一些類似的查詢。爲了減少重複的工作,我們可以將這些類似的查詢寫成模板,在後續只需要傳遞不同的參數來調用模板獲取結果。 模板的保存和刪","date": "2019-12-19 23:48:14","read_num": 2,"comment_num": 0}
{"index":{"_index":"article","_id":2}}
{"article_type": "原創","article_title": "Elasticsearch查詢——URI Search(簡單查詢字符串)","content": "簡單查詢字符串——URI Search 實際業務中我們通常都是使用一個完整的請求體從elasticsearch獲得數據。然而在有些時候我們爲了調試系統或者數據的時候需要臨時進行一些簡單的查詢時候,編寫完整的請求體JSON可能會稍微麻煩。而elasticsearch提供了一種基於URI的簡單的查詢方","date": "2019-12-18 21:58:18","read_num": 10,"comment_num": 0}
{"index":{"_index":"article","_id":3}}
{"article_type": "原創","article_title": "Elasticsearch攝取節點(十)——GeoIP以及Grok處理器","content": "IP解析處理器(GeoIP Processor) 處理器作用 GeoIP Processor主要是根據IP地址解析出具體的地理位置信息的處理器。此處理器需要配合Maxmind數據庫中的數據。 ingest-geoip模塊附帶的GeoLite2 City、GeoLite2 Country和GeoLi","date": "2019-12-18 20:52:10","read_num": 4,"comment_num": 0}
{"index":{"_index":"article","_id":4}}
{"article_type": "原創","article_title": "Elasticsearch腳本使用","content": "如何使用Elasticsearch腳本 Elasticsearch默認腳本語言爲Painless。其他lang插件使您可以運行以其他語言編寫的腳本。 語言 沙盒 是否需要插件 備註 painless 是 內置的 默認腳本語言 expression 是 內置的 快速的自定義排名和","date": "2019-12-14 15:10:07","read_num": 11,"comment_num": 0}
......

執行下面請求之後在返回內容中除了常規的數據匹配之外還存在highlight對象,此對象中會將查詢字段中和查詢條件一直的內容使用預設的HTML標籤進行包裹。

GET article/_search
{
    "size":5,
    "query": {
        "match": {
            "content": "簡單的查詢"
        }
    },
    "highlight": {
        "boundary_scanner_locale":"zh_CN",
        "fields": {
            "content": {
                "pre_tags": [
                    "<em>"
                ],
                "post_tags": [
                    "</em>"
                ]
            }
        }
    }
}

## 返回內容

"highlight" : {
  "content" : [
	"<em>簡</em><em>單</em><em>查</em><em>詢</em>字符串——URI Search 實際業務中我們通常都是使用一個完整<em>的</em>請求體從elasticsearch獲得數據。",
	"然而在有些時候我們爲了調試系統或者數據<em>的</em>時候需要臨時進行一些<em>簡</em><em>單</em><em>的</em><em>查</em><em>詢</em>時候,編寫完整<em>的</em>請求體JSON可能會稍微麻煩。而elasticsearch提供了一種基於URI<em>的</em><em>簡</em><em>單</em><em>的</em><em>查</em><em>詢</em>方"
  ]
}

高亮設置

下面的參數可以設置在highlight的下一級此時未全局設置,也可以設置在字段的下一級,此時爲字段設置。單個字段的設置優先級高於全局設置。比如下面的請求中最終匹配的短語會被

包裹.

GET article/_search
{
    "size":5,
    "query": {
        "match": {
            "content": "簡單的查詢"
        }
    },
    "highlight": {
        "boundary_scanner_locale":"zh_CN",
        "boundary_scanner":"sentence",
        "fragmenter":"span", 
        "pre_tags": ["<em>"],
        "post_tags": ["</em>"],
        "fields": {
            "content": {
               "pre_tags": [
                    "<h1>"
                ],
                "post_tags": [
                    "</h1>"
                ] 
            }
        }
    }
}

高亮參數

參數 說明
boundary_chars 包含每個邊界字符的字符串。默認爲,! ?\ \ n。
boundary_max_scan 掃描邊界字符的距離。默認爲20。
boundary_scanner 指定如何分割突出顯示的片段,支持chars, sentence, or word三種方式。
boundary_scanner_locale 用來設置搜索和確定單詞邊界的本地化設置,此參數使用語言標記的形式(“en-US”, “fr-FR”, “ja-JP”)
encoder 表示代碼段應該是HTML編碼的:默認(無編碼)還是HTML (HTML-轉義代碼段文本,然後插入高亮標記)
fields 指定檢索高亮顯示的字段。可以使用通配符來指定字段。例如,可以指定comment_*來獲取以comment_開頭的所有文本和關鍵字字段的高亮顯示。
force_source 根據源高亮顯示。默認值爲false。
fragmenter 指定文本應如何在突出顯示片段中拆分:支持參數simple或者span。
fragment_offset 控制要開始突出顯示的空白。僅在使用fvh highlighter時有效。
fragment_size 字符中突出顯示的片段的大小。默認爲100。
highlight_query 突出顯示搜索查詢之外的其他查詢的匹配項。這在使用重打分查詢時特別有用,因爲默認情況下高亮顯示不會考慮這些問題。
matched_fields 組合多個匹配結果以突出顯示單個字段,對於使用不同方式分析同一字符串的多字段。所有的matched_fields必須將term_vector設置爲with_positions_offsets,但是隻有將匹配項組合到的字段纔會被加載,因此只有將store設置爲yes才能使該字段受益。只適用於fvh highlighter。
no_match_size 如果沒有要突出顯示的匹配片段,則希望從字段開頭返回的文本量。默認爲0(不返回任何內容)。
number_of_fragments 返回的片段的最大數量。如果片段的數量設置爲0,則不會返回任何片段。相反,突出顯示並返回整個字段內容。當需要突出顯示短文本(如標題或地址),但不需要分段時,使用此配置非常方便。如果number_of_fragments爲0,則忽略fragment_size。默認爲5。
order 設置爲score時,按分數對突出顯示的片段進行排序。默認情況下,片段將按照它們在字段中出現的順序輸出(order:none)。將此選項設置爲score將首先輸出最相關的片段。每個高亮應用自己的邏輯來計算相關性得分。
phrase_limit 控制文檔中所考慮的匹配短語的數量。防止fvh highlighter分析太多的短語和消耗太多的內存。提高限制會增加查詢時間並消耗更多內存。默認爲256。
pre_tags 與post_tags一起使用,定義用於突出顯示文本的HTML標記。默認情況下,突出顯示的文本被包裝在和標記中。指定爲字符串數組。
post_tags 與pre_tags一起使用,定義用於突出顯示文本的HTML標記。默認情況下,突出顯示的文本被包裝在和標記中。指定爲字符串數組。
require_field_match 默認情況下,只突出顯示包含查詢匹配的字段。將require_field_match設置爲false以突出顯示所有字段。默認值爲true。
tags_schema 設置爲使用內置標記模式的樣式。
type 使用的高亮模式:unified, plain, or fvh. 默認爲 unified。

高亮參數內容的補充

boundary_scanner

指定如何分割突出顯示的片段,支持chars, sentence, or word三種方式。默認unified highlighter使用
sentence,fvh highlighter使用chars。

  • chars

使用boundary_chars指定的字符突出顯示邊界。boundary_max_scan設置控制掃描邊界字符的距離。只適用於fvh highlighter。

  • sentence

根據Java的BreakIterator確定,在下一個句子邊界處中斷突出顯示的片段。配置了此參數後上面例子返回內容,可以看到其每個分段都是一個句子

"highlight" : {
  "content" : [
	"<em>簡</em><em>單</em><em>查</em><em>詢</em>字符串——URI Search 實際業務中我們通常都是使用一個完整<em>的</em>請求體從elasticsearch獲得數據。",
	"然而在有些時候我們爲了調試系統或者數據<em>的</em>時候需要臨時進行一些<em>簡</em><em>單</em><em>的</em><em>查</em><em>詢</em>時候,編寫完整<em>的</em>請求體JSON可能會稍微麻煩。而elasticsearch提供了一種基於URI<em>的</em><em>簡</em><em>單</em><em>的</em><em>查</em><em>詢</em>方"
  ]
}
  • word

根據Java的BreakIterator確定,在下一個單詞邊界處中斷突出顯示的片段。使用此參數上面的例子返回內容,此時每個分段並不是一個完整的句子。

"highlight" : {
  "content" : [
	"<em>簡</em><em>單</em><em>查</em><em>詢</em>字符串",
	"實際業務中我們通常都是使用一個完整<em>的</em>請求體從",
	"然而在有些時候我們爲了調試系統或者數據<em>的</em>時候需要臨時進行一些<em>簡</em><em>單</em><em>的</em><em>查</em><em>詢</em>時候",
	"編寫完整<em>的</em>請求體",
	"<em>的</em><em>簡</em><em>單</em><em>的</em><em>查</em><em>詢</em>方"
  ]
}

boundary_scanner_locale

用來設置搜索和確定單詞邊界的本地化設置

  1. 可以通過https://docs.oracle.com/javase/8/docs/api/java/util/Locale.html#forLanguageTag-java.lang.String-獲得更多語言標籤

  2. 默認參數爲[Locale.ROOT]{https://docs.oracle.com/javase/8/docs/api/java/util/Locale.html#ROOT}

fragmenter

指定文本應如何在突出顯示片段中拆分。只適用於plain highlighter。默認爲span。

  1. simple:將文本分割成相同大小的片段
  2. span:將文本分割爲大小相同的片段,但儘量避免在突出顯示的術語之間分割文本。這在查詢短語時很有用

type

type字段允許強制使用特定的高亮策略。可以配置的參數:unified, plain and fvh。下面是一個使用plain策略的例子:

GET article/_search
{
    "query" : {
        "match": { "content": "簡單的查詢" }
    },
    "highlight" : {
        "fields" : {
            "content" : {"type" : "plain"}
        }
    }
}

三種不同的高亮策略的區別

  1. unified(通用高亮策略)

其使用的是Lucene的Unified Highlighter。此高亮策略將文本分解成句子,並使用BM25算法對單個句子進行評分,支持精確的短語和多術語(模糊、前綴、正則表達式)突出顯示。這個是默認的高亮策略。

  1. plain (普通高亮策略)

其使用的是Lucene的standard Lucene highlighter。它試圖在理解詞的重要性和短語查詢中的任何詞定位標準方面反映查詢匹配邏輯。此高亮策略是和在單個字段中突出顯示簡單的查詢匹配。如果想用複雜的查詢在很多文檔中突出顯示很多字段,還是使用unified

  1. Fast vector highlighter(快速向量策略)

其使用的是Lucene的Fast Vector highlighter。使用此策略需要在映射中將對應字段中屬性term_vector設置爲with_positions_offsets。這個策略以後會單獨介紹。

pre_tags和post_tags

默認情況下,高亮顯示將以和包裝突出顯示的文本。這可以通過設置pre_tags和post_tags來控制,例如:

GET article/_search
{
    "size":5,
    "query": {
        "match": {
            "content": "簡單的查詢"
        }
    },
    "highlight": {
        "boundary_scanner_locale":"zh_CN",
        "fields": {
            "content": {
               "pre_tags": [
                    "<h1>"
                ],
                "post_tags": [
                    "</h2>"
                ] 
            }
        }
    }
}

當然也可以使用系統預設的標籤模式:

GET article/_search
{
    "size":5,
    "query": {
        "match": {
            "content": "簡單的查詢"
        }
    },
    "highlight": {
        "boundary_scanner_locale":"zh_CN",
        "tags_schema" : "styled",
        "fields": {
            "content": {
                
            }
        }
    }
}

fragment_size 和 number_of_fragments

fragment_size主要控制了每個高亮片段的大小,而number_of_fragments控制了返回多少個高亮片段。下面例子中就是控制返回兩個長度10的片段

GET article/_search
{
    "query": {
        "bool": {
            "must": [
                {
                    "match": {
                        "content": "簡單的查詢"
                    }
                }
            ]
        }
    },
    "highlight": {
        "boundary_scanner_locale": "zh_CN",
        "fields": {
            "content": {
              "fragment_size" : 10,
              "number_of_fragments" : 2
            }
        }
    }
}

order

order控制了返回對象中highlight片段的排序。下面例子中返回的高亮片段將會根據分數順序輸出。假如設置了none則是按照順序輸出。

GET article/_search
{
    "query": {
        "bool": {
            "must": [
                {
                    "match": {
                        "content": "簡單的查詢"
                    }
                }
            ]
        }
    },
    "highlight": {
        "order" : "score",
        "boundary_scanner_locale": "zh_CN",
        "fields": {
            "content": {}
        }
    }
}

對一個字段進行查詢的時候希望高亮其他字段

在請求參數highlight中可以設置多個字段,同時需要爲每個字段配置highlight_query。通過配置這個字段可以實現對content進行匹配查詢同時高亮article_titlecontent字段的內容。同時使用此方法可以實現使用使用查詢條件查詢,而最終高亮字符串內容。

GET article/_search
{
    "query": {
        "match": {
            "content": "查詢"
        }
    },
    "highlight": {
        "fields": {
            "content": {
                "type": "unified",
                "highlight_query": {
                    "bool": {
                        "must": {
                            "match": {
                                "content": {
                                    "query": "字符串"
                                }
                            }
                        },
                        "minimum_should_match": 0
                    }
                }
            },
            "article_title": {
                "type": "unified",
                "highlight_query": {
                    "bool": {
                        "must": {
                            "match": {
                                "article_title": {
                                    "query": "字符串"
                                }
                            }
                        },
                        "minimum_should_match": 0
                    }
                }
            }
        }
    }
}

highlighter如何確定高亮內容

爲了從查詢的詞彙中獲得搜索片段位置,高亮策略顯示需要知道原始文本中每個單詞的起始和結束字符偏移量。目前根據模式不同獲取這些數據途徑不同

  1. 檢索列表,如果在映射中index_options設置了offsets,unified會將其中數據應用在文檔中,而不會重新分析文本。它直接對文檔進行原始查詢,並從索引中提取匹配的偏移數據。在字段內容很大的時候,使用此配置很重要,因爲它不需要重新分析文本內容。和term_vectors相比,它還需要更少的磁盤空間。
  2. 術語向量,如果在映射中term_vector設置爲with_positions_offsets則unified highlighter使用term_vector來突出顯示字段。對於大字段(大於1MB)和多術語查詢它的速度會比較快。而fvh highlighter總是使用term_vector
  3. 普通的高亮策略(
    Plain highlighting),當沒有其他選擇的時候,unified highlighter使用此模式,他在內存中創建一個小的索引(index),通過運行Lucene的查詢執行計劃來訪問文檔的匹配信息,對需要高亮顯示的每個字段和每個文檔進行處理。plain highlighter總是使用此策略。注意此方式在大型文本上可能需要大量的時間和內存。在使用此策略時候可以設置分析的文本字符的最大數量限制爲1000000。這個數值可以通過修改索引的index.highlight.max_analyzed_offset參數來改變。

個人水平有限,上面的內容可能存在沒有描述清楚或者錯誤的地方,假如開發同學發現了,請及時告知,我會第一時間修改相關內容。假如我的這篇內容對你有任何幫助的話,麻煩給我點一個贊。你的點贊就是我前進的動力。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章