第五章 Elasticsearch Text analysis 文本分析
摘要
文本分析是將非結構化文本(例如電子郵件的正文或產品說明)轉換爲針對搜索優化的結構化格式的過程。
當對text
字段建立索引或搜索時,Elasticsearch 會執行文本分析。
但是,如果您使用text字段或文本搜索未返回預期的結果,則配置文本分析通常會有所幫助。如果您正在使用Elasticsearch執行以下操作,則還應該研究分析配置:
- 建立一個搜索引擎
- 非結構化數據
- 優化搜索特定語言
- 進行詞典或語言研究
概述
文本分析使Elasticsearch能夠執行全文搜索,其中搜索返回所有相關結果,而不僅僅是精確匹配。
如果您進行搜索Quick fox jumps
,則可能需要包含的文檔:A quick brown fox jumps over the lazy dog
,還可能需要包含諸如fast fox
或的相關單詞的文檔foxes leap
。
Tokenization 標記化
分析使得標記化的全文搜索成爲可能。將文本分解成爲較小的塊,成爲標記(token
)。在英語語義下,通常爲單個單詞。
如果您將詞組索引the quick brown fox jumps
爲單個單詞,並且用戶搜索的時quick fox
,則不會將其視爲匹配項。但是,如果您對短語進行標記,並分別索引單個單詞,則可以單獨查詢字符串中的術語,這意味着他們可以通過搜索進行匹配quick fox
,fox brown
或其他變化。
Normalization 正常化
tokenization 可以匹配單個術語,但每個標記仍是機械的匹配,這就意味着:
1. quick
和Quick
不會匹配,即使是你希望它們之間會相互匹配。
2. fox
和foxes
擁有相同的詞根,但也不會相互匹配
3. 同義詞之間也不會相互匹配
爲了解決這些問題,文本分析可以將這些標記標準化爲標準格式。這樣,您就可以匹配與搜索字詞不完全相同但足夠相似但仍具有相關性的標記。
爲了保證搜索的準確性,您可以把搜索時的文本分析和索引裏的文本分析設置爲一致。
Customize text analysis 自定義文本分析
文本分析由分析器執行,它是控制整個過程的一組規則。
Elasticsearch包含一個默認的分析器,稱爲 標準分析器,它對於開箱即用的大多數用例都適用。
如果要定製搜索體驗,則可以選擇其他 內置分析儀,甚至可以 配置自定義分析儀。定製分析器使您可以控制分析過程的每個步驟,包括:
- 標記化 之前 對文本的更改
- 文本如何轉換爲令牌
- 在索引或搜索之前對令牌進行規範化更改
Text analysis concepts 文本分析概念
解析分析器
一個分析器,無論是內置的還是自定義的,都是一個包,包含三個最基本的模塊:character filters, tokenizers, and token filters
內置的分析器將這些構件預先打包爲適合不同語言和文本類型的分析器。Elasticsearch還公開了各個構建基塊,以便可以將它們組合以定義新的custom分析器。
character filters 字符過濾器
一個character filters
接受一個原始的文本,作爲一個字符串的流,並且可以添加,移除,改變。一個分析器,可能會擁有零個或者多個character filters
,按照一定的順序使用。
tokenizer 分詞器
一個tokenizer
接受一個字符流,將他們拆分成獨立的標記,並輸出。
分詞器還負責記錄每個術語的順序或位置以及該術語代表的原始單詞的開始和結束字符偏移量。
分析器必須僅具有一個標記器。
token filters 標記過濾器
一個token filters
接受一個標記流,可能會添加、移除、改變一個標記。但是不允許改變,標記在原文本中的位置或者字符的偏移量。分析器可能具有零個或多個按順序應用的令牌過濾器。
索引和分析
文本分析會出現在兩種情況下:
- 添加文檔(index time),text字段會被分析
- 全文搜索, 對text字段進行全文搜索時,會對匹配項進行文本分析
每次使用的分析器或一組分析規則分別稱爲索引分析器或搜索分析器。
如何一起使用索引和搜索分析
在默認情況下,或是說,在大多數情況下,會使用相同的分析器。確保搜索和索引的一致性。
示例
The QUICK brown foxes jumped over the dog!
分析成,[ quick, brown, fox, jump, over, dog ]
可以使用下面的API,來獲取文本分析結果
GET /_analyze
{
"analyzer" : "standard",
"text" : ["this is a test", "the second text"]
}
Stemming 獲取單詞的詞根
Stemming 就是將原單詞,還原成詞根的形式。這樣就保證在搜索過程中,匹配單詞的變體。在某些情況下,詞幹的詞根形式可能不是真實的詞,但這不影響搜索。如果將單詞的所有變體都簡化成爲相同的詞根形式,則他們將會正確的匹配。
Stemmer Token filter 詞幹標記過濾器
在Elasticsearch 中,抽取詞幹是由stemmer token filter完成的,這些過濾器可以基於一定的方法完成。
- 算法(Algorithmic stemmers),通過一定的規則抽取
- 字典(dictionary stemmers),通過字典查找
由於詞幹會改變標記,因此建議在索引和搜索期間使用相同的詞幹令牌過濾器
Algorithmic stemmers 算法提取詞幹
這種詞幹抽取器,爲每個詞提供一系列規則,將其簡化爲詞根形式。
優點:
- 需要很少的設置,開箱即用
- 使用較小的內存
- 比字典的方式要快
但是,大多數算法詞幹僅會更改單詞的現有文本。這意味着它們可能不適用於不包含其詞根形式的不規則單詞。
以下是常用的算法:
stemmer
,它提供了幾種語言的算法詞幹,其中一些帶有其他變體。kstem
,是英語的詞幹分析器,它將算法詞幹與內置詞典結合在一起。porter_stem
,是我們推薦的英語算法提取器。snowball
,它對幾種語言使用 基於Snowball的詞幹規則。
Dictionary stemmers 字典提取詞幹
查找提供的字典中的詞,使用字典中的詞幹。
- 阻止不規則單詞
- 辨別拼寫相似但概念上不相關的單詞
在實踐中,算法詞幹分析器通常優於字典詞幹分析器。這是因爲詞幹分析器具有以下缺點:
- 詞典質量,詞典詞幹僅與其詞典一樣好。爲了運作良好,這些詞典必須包含大量單詞,定期更新並隨語言趨勢而變化。通常,在提供字典時,它是不完整的,並且其某些條目已經過時了。
- 大小和性能,詞典詞幹必須將其詞典中的所有單詞,前綴和後綴加載到內存中。這會佔用大量RAM。低質量詞典在刪除前綴和後綴時也可能效率較低,這可能會大大減慢詞幹的處理速度。
control stemming 限制詞幹
有些時候,詞幹分析器會將拼寫類似但是含義不同的詞,定義爲同一個詞幹。爲了防止這種情況,可以使用control stemming,如下所示:
stemmer_override
,可讓您定義用於阻止特定令牌的規則。
keyword_marker
,將指定的標記標記爲關鍵字。關鍵字令牌不會被後續的詞幹令牌過濾器阻止。
conditional
,可用於將令牌標記爲關鍵字,類似於keyword_marker過濾器。
對於內置的語言分析器,您還可以使用參數stem_exclusion
來制定不會被阻之的單詞列表。
Token graphs 標記圖
當tokenizer將文本轉化成標記流時,他還會記錄以下內容:
- 每個標記的位置
- 位置之間的間隔
使用這些信息,您可以爲流創建一個有向無環圖,成爲tonen graphs。在圖中,每個位置代表一個節點。每個標記都表示只想下一個位置的邊或弧。
一些標記過濾器可以將新的標記添加到現有的流中。同義詞通常與現有的標記的位置相同。
配置文本分析
在默認情況下,Elasticsearch 使用默認的標準分析器,對於大多數語言,是開箱即用的。
如果默認的標準分析器不符合您的需求,可以嘗試使用Elasticsearch 提供的其他分析器,內置分析儀不需要配置,但是可以使用一些支持選項來調整其行爲。例如,您可以爲標準分析器配置要刪除的自定義停用詞列表。
測試分析器
最簡單的用法
POST _analyze
{
/*指定分析器*/
"analyzer": "whitespace",
/*指定要分析的文本*/
"text": "The quick brown fox."
}
指定其他參數
- 一個分詞器
- 零個或多個標記過濾器
- 零個或多個字符過濾器
POST _analyze
{
"tokenizer": "standard",
"filter": [ "lowercase", "asciifolding" ],
"text": "Is this déja vu?"
}
使用現有的索引中文本字段的分析器
PUT my_index
{
"settings": {
"analysis": {
"analyzer": {
"std_folded": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"asciifolding"
]
}
}
}
},
"mappings": {
"properties": {
"my_text": {
"type": "text",
"analyzer": "std_folded"
}
}
}
}
GET my_index/_analyze
{
"analyzer": "std_folded",
"text": "Is this déjà vu?"
}
GET my_index/_analyze
{
"field": "my_text",
"text": "Is this déjà vu?"
}
配置標準分析器
標準分析器可以開箱即用,但也可以修改一些配置來控制它的行爲。例如,可以將標準分析器配置爲支持停用詞列表。參考下面示例:
- 在標準分析器的基礎上定義了一個
std_english
分析器,但是配置爲刪除英語停用詞的預定義列表 - 第一個
GET
示例中,my_text
字段直接使用標準分詞器,沒有被移除停止使用後的詞,結果是[the, old, brown, cow]
3.第二個GET示例中,my_text.english
使用std_english
分詞器,會移除停止使用的詞,結果是[old, brown, cow]
PUT my_index
{
"settings": {
"analysis": {
"analyzer": {
"std_english": {
"type": "standard",
"stopwords": "_english_"
}
}
}
},
"mappings": {
"properties": {
"my_text": {
"type": "text",
"analyzer": "standard",
"fields": {
"english": {
"type": "text",
"analyzer": "std_english"
}
}
}
}
}
}
POST my_index/_analyze
{
"field": "my_text",
"text": "The old brown cow"
}
POST my_index/_analyze
{
"field": "my_text.english",
"text": "The old brown cow"
}
自定義一個分析器
當標準分析器無法滿足使用需求是,可以自定義一個分析器:
- 一個分詞器
- 零個或多個標記過濾器
- 零個或多個字符過濾器
參數
參數 | 含義 |
---|---|
tokenizer | 內置或自定義的標記器。(需要) |
char_filter | 內置或自定義字符過濾器的可選數組 。 |
filter | 內置或自定義標記過濾器的可選數組 。 |
position_increment_gap | 在爲文本值數組建立索引時,Elasticsearch在一個值的最後一項和下一個值的第一項之間插入一個假的“空白”,以確保詞組查詢與來自不同數組元素的兩項不匹配。默認爲100。查看position_increment_gap更多。 |
自定義過濾器示例
指定分析器
Elasticsearch 提供了多種方法來指定內置或自定義的分析器:
- 按text字段,索引或查詢
- 用於索引或搜索
把事情簡單化,在不同層次和不同的時間,指定分析儀的靈活性是偉大的… 不過也要僅在需要時它。
在大多數情況下,一種簡單的方法最有效:爲每個text
字段指定一個分析器,如爲 字段指定分析器中所述。這種方法與Elasticsearch的默認行爲很好地配合使用,使您可以使用同一分析器進行索引和搜索。它還使您可以使用get mapping API
快速查看哪個分析器應用於哪個字段。如果通常不爲索引創建映射,則可以使用 索引模板來達到類似的效果。
Elasticsearch 如何確定索引分析器
Elasticsearch 依次檢查以下參數,來確定要使用的索引分析器:
1. analyzer
,字段映射參數
2. analysis.analyzer.default
,默認分析器
3. 如未指定,則使用標準分析器
如何確定搜索分析器
在大多數情況下,無需指定其他搜索分析器。這樣做可能會對相關性產生負面影響,並導致意外的搜索結果。
如果您選擇指定一個單獨的搜索分析器,我們建議您在部署到生產環境之前徹底 測試您的分析配置。
在搜索時,Elasticsearch通過依次檢查以下參數來確定要使用的分析器:
analyzer
搜索查詢中 的參數。請參閱爲查詢指定搜索分析器。search_analyzer
字段 的映射參數。請參閱爲字段指定搜索分析器。analysis.analyzer.default_search
。請參閱爲索引指定默認搜索分析器。analyzer
字段 的映射參數。請參閱爲字段指定分析器。- 如未指定,則使用標準分析器
可以點擊查看示例
內置分析器
- 標準分析器(
Standard Analyzer
):根據Unicode文本分段算法的定義,分析器將文本劃分爲單詞邊界上的多個術語。它刪除大多數標點符號,小寫術語,並支持停用詞 - 簡單分析器(
Simple Analyzer
):當分析器遇到非字母的字符時,它將文本劃分成爲多個術語,將所有術語轉化爲小寫 - 空白分析器(
Whitespace Analyzer
):任何空白字符都作爲分隔符,將文本劃分爲術語 - 停用分析器(
Stop Analyzer
):和簡單分析器類似,而且支持去除停用詞。 - 關鍵字分析器(
Keyword Analyzer
):將整個文本視爲一個術語 - 模式分析器(
Pattern Analyzer
):使用正則表達式,將文本分割。支持小寫文本,和停用詞 - 語言分析器(
Language Analyzer
):對於特定的語言 - 指紋分析器(
Fingerprint Analyzer
):可創建可用於重複檢測的指紋。 - 自定義分析器:如果你沒有找到一個分析儀適合您的需求,您可以創建一個分析器,結合相應的字符過濾器, 標記生成器,和標記過濾。
內置分詞器
內置標記過濾器
內置字符過濾器
字符過濾器用於預處理字符流,然後再將其傳遞給令牌生成器。
字符過濾器將原始文本作爲字符流接收,並且可以通過添加,刪除或更改字符來轉換流。例如,可以使用字符過濾器將印度阿拉伯數字(٠ ١٢٣٤٥٦٧٨ ٩)轉換爲其等效的阿拉伯語-拉丁語(0123456789),或從流中剝離HTML元素。
Elasticsearch有許多內置的字符過濾器,可用於構建 自定義分析器。
- HTML字符過濾器,該
html_strip
字符過濾帶出HTML元素,比如像和解碼HTML實體&。 - 映射字符過濾器,該
mapping
字符過濾器替換指定更換指定的字符串中的任何事件。 - 正則表達式替換字符過濾器,
pattern_replace
字符過濾器將所有與正則表達式匹配的字符替換爲指定的替換。