ElasticSearch 分詞器

- 作者: 博學谷狂野架構師
- GitHub:GitHub地址 (有我精心準備的130本電子書PDF)
只分享干貨、不吹水,讓我們一起加油!??
概述
分詞器的主要作用將用戶輸入的一段文本,按照一定邏輯,分析成多個詞語的一種工具
什么是分詞器
顧名思義,文本分析就是把全文本轉換成一系列單詞(term/token)的程序,也叫分詞,在 ES 中,Analysis 是通過分詞器(Analyzer) 來實作的,可使用 ES 內置的分析器或者按需定制化分析器,
舉一個分詞簡單的例子:比如你輸入 Mastering Elasticsearch,會自動幫你分成兩個單詞,一個是 mastering,另一個是 elasticsearch,可以看出單詞也被轉化成了小寫的,

分詞器的構成
分詞器是專門處理分詞的組件,分詞器由以下三部分組成:
組成部分
character filter
接收原字符流,通過添加、洗掉或者替換操作改變原字符流
例如:去除文本中的html標簽,或者將羅馬數字轉換成阿拉伯數字等,一個字符過濾器可以有零個或者多個
tokenizer
簡單的說就是將一整段文本拆分成一個個的詞,
例如拆分英文,通過空格能將句子拆分成一個個的詞,但是對于中文來說,無法使用這種方式來實作,在一個分詞器中,有且只有一個tokenizeer
token filters
將切分的單詞添加、洗掉或者改變
例如將所有英文單詞小寫,或者將英文中的停詞a洗掉等,在token filters中,不允許將token(分出的詞)的position或者offset改變,同時,在一個分詞器中,可以有零個或者多個token filters.
分詞順序

同時 Analyzer 三個部分也是有順序的,從圖中可以看出,從上到下依次經過 Character Filters,Tokenizer 以及 Token Filters,這個順序比較好理解,一個文本進來肯定要先對文本資料進行處理,再去分詞,最后對分詞的結果進行過濾,
索引和搜索分詞
文本分詞會發生在兩個地方:
創建索引:當索引檔案字符型別為text時,在建立索引時將會對該欄位進行分詞,搜索:當對一個text型別的欄位進行全文檢索時,會對用戶輸入的文本進行分詞,
配置分詞器
默認ES使用
standard analyzer,如果默認的分詞器無法符合你的要求,可以自己配置
分詞器測驗
可以通過
_analyzerAPI來測驗分詞的效果,
COPY# 過濾html 標簽
POST _analyze
{
"tokenizer":"keyword", #原樣輸出
"char_filter":["html_strip"], # 過濾html標簽
"text":"<b>hello world<b>" # 輸入的文本
}

指定分詞器
使用地方
分詞器的使用地方有兩個:
- 創建索引時
- 進行搜索時
創建索引時指定分詞器
如果設定手動設定了分詞器,ES將按照下面順序來確定使用哪個分詞器:
- 先判斷欄位是否有設定分詞器,如果有,則使用欄位屬性上的分詞器設定
- 如果設定了
analysis.analyzer.default,則使用該設定的分詞器 - 如果上面兩個都未設定,則使用默認的
standard分詞器
欄位指定分詞器
為title屬性指定分詞器
COPYPUT my_index
{
"mappings": {
"properties": {
"title":{
"type":"text",
"analyzer": "whitespace"
}
}
}
}
設定默認分詞器
COPYPUT my_index
{
"settings": {
"analysis": {
"analyzer": {
"default":{
"type":"simple"
}
}
}
}
}
搜索時如何確定分詞器
在搜索時,通過下面引數依次檢查搜索時使用的分詞器:
- 搜索時指定
analyzer引數 - 創建mapping時指定欄位的
search_analyzer屬性 - 創建索引時指定
setting的analysis.analyzer.default_search - 查看創建索引時欄位指定的
analyzer屬性 - 如果上面幾種都未設定,則使用默認的
standard分詞器,
指定analyzer
搜索時指定analyzer查詢引數
COPYGET my_index/_search
{
"query": {
"match": {
"message": {
"query": "Quick foxes",
"analyzer": "stop"
}
}
}
}
指定欄位analyzer
COPYPUT my_index
{
"mappings": {
"properties": {
"title":{
"type":"text",
"analyzer": "whitespace",
"search_analyzer": "simple"
}
}
}
}
指定默認default_seach
COPYPUT my_index
{
"settings": {
"analysis": {
"analyzer": {
"default":{
"type":"simple"
},
"default_seach":{
"type":"whitespace"
}
}
}
}
}
內置分詞器
es在索引檔案時,會通過各種型別
Analyzer對text型別欄位做分析,
不同的 Analyzer 會有不同的分詞結果,內置的分詞器有以下幾種,基本上內置的 Analyzer 包括 Language Analyzers 在內,對中文的分詞都不夠友好,中文分詞需要安裝其它 Analyzer
| 分析器 | 描述 | 分詞物件 | 結果 |
|---|---|---|---|
| standard | 標準分析器是默認的分析器,如果沒有指定,則使用該分析器,它提供了基于文法的標記化(基于 Unicode 文本分割演算法,如 Unicode 標準附件 # 29所規定) ,并且對大多數語言都有效, | The 2 QUICK Brown-Foxes jumped over the lazy dog’s bone. | [ the, 2, quick, brown, foxes, jumped, over, the, lazy, dog’s, bone ] |
| simple | 簡單分析器將文本分解為任何非字母字符的標記,如數字、空格、連字符和撇號、放棄非字母字符,并將大寫字母更改為小寫字母, | The 2 QUICK Brown-Foxes jumped over the lazy dog’s bone. | [ the, quick, brown, foxes, jumped, over, the, lazy, dog, s, bone ] |
| whitespace | 空格分析器在遇到空白字符時將文本分解為術語 | The 2 QUICK Brown-Foxes jumped over the lazy dog’s bone. | [ The, 2, QUICK, Brown-Foxes, jumped, over, the, lazy, dog’s, bone. ] |
| stop | 停止分析器與簡單分析器相同,但增加了洗掉停止字的支持,默認使用的是 _english_ 停止詞, |
The 2 QUICK Brown-Foxes jumped over the lazy dog’s bone. | [ quick, brown, foxes, jumped, over, lazy, dog, s, bone ] |
| keyword | 不分詞,把整個欄位當做一個整體回傳 | The 2 QUICK Brown-Foxes jumped over the lazy dog’s bone. | [The 2 QUICK Brown-Foxes jumped over the lazy dog’s bone.] |
| pattern | 模式分析器使用正則運算式將文本拆分為術語,正則運算式應該匹配令牌分隔符,而不是令牌本身,正則運算式默認為 w+ (或所有非單詞字符), |
The 2 QUICK Brown-Foxes jumped over the lazy dog’s bone. | [ the, 2, quick, brown, foxes, jumped, over, the, lazy, dog, s, bone ] |
| 多種西語系 arabic, armenian, basque, bengali, brazilian, bulgarian, catalan, cjk, czech, danish, dutch, english等等 | 一組旨在分析特定語言文本的分析程式, |
中文擴展分析器
中文分詞器最簡單的是ik分詞器,還有jieba分詞,哈工大分詞器等
| 分詞器 | 描述 | 分詞物件 | 結果 |
|---|---|---|---|
| ik_smart | ik分詞器中的簡單分詞器,支持自定義字典,遠程字典 | 學如逆水行舟,不進則退 | [學如逆水行舟,不進則退] |
| ik_max_word | ik_分詞器的全量分詞器,支持自定義字典,遠程字典 | 學如逆水行舟,不進則退 | [學如逆水行舟,學如逆水,逆水行舟,逆水,行舟,不進則退,不進,則,退] |
詞語分詞
標準分詞器(Standard Tokenizer)
根據standardUnicode文本分段演算法的定義,將文本劃分為多個單詞邊界的上的術語
它是 ES 默認的分詞器,它會對輸入的文本按詞的方式進行切分,切分好以后會進行轉小寫處理,默認的 stopwords 是關閉的,

使用案例
下面使用 Kibana 看一下它是怎么樣進行作業的
原始內容
COPYIn 2020, Java is the best language in the world.
測驗分詞
在 Kibana 的開發工具(Dev Tools)中指定 Analyzer 為
standard,并輸入文本In 2020, Java is the best language in the world.,然后我們運行一下:
COPYGET _analyze
{
"text":"In 2020, Java is the best language in the world.",
"analyzer": "standard"
}

可以看出是按照空格、非字母的方式對輸入的文本進行了轉換,比如對 Java 做了轉小寫,對一些停用詞也沒有去掉,比如 in,其中 token 為分詞結果;start_offset 為起始偏移;end_offset 為結束偏移;position 為分詞位置,
可配置項
| 選項 | 描述 |
|---|---|
| max_token_length | 最大令牌長度,如果看到令牌超過此長度,則將其max_token_length間隔分割,默認為255, |
| stopwords | 預定義的停用詞串列,例如english或包含停用詞串列的陣列,默認為none, |
| stopwords_path | 包含停用詞的檔案的路徑, |
COPY{
"settings": {
"analysis": {
"analyzer": {
"my_english_analyzer": {
"type": "standard",
"max_token_length": 5,
"stopwords": "_english_"
}
}
}
}
}
簡單分詞器(Letter Tokenizer)
當simple分析器遇到非字母的字符時,它會將文本劃分為多個術語,它小寫所有術語,對于中文和亞洲很多國家的語言來說是無用的

它只包括了 Lower Case 的 Tokenizer,它會按照非字母切分,非字母的會被去除,最后對切分好的做轉小寫處理,然后接著用剛才的輸入文本,分詞器換成 simple 來進行分詞,運行結果如下:
使用案例
原始內容
COPYIn 2020, Java is the best language in the world.
測驗分詞
COPYGET _analyze
{
"text":"In 2020, Java is the best language in the world.",
"analyzer": "simple"
}

空白分詞器(Whitespace Tokenizer)
它非常簡單,根據名稱也可以看出是按照空格進行切分的
該whitespace分析儀將文本分為方面每當遇到任何空白字符,和上面的分詞器不同,空白分詞器默認并不會將內容轉換為小寫,

使用案例
原始內容
COPYIn 2020, Java is the best language in the world.
測驗分詞
COPYGET _analyze
{
"text":"In 2020, Java is the best language in the world.",
"analyzer": "whitespace"
}

電子郵件分詞器(UAX URL Email Tokenizer)
此分詞器主要是針對email和url地址進行關鍵內容的標記,
使用案例
原始內容
COPY"Email me at [email protected]"
測驗分詞
COPYGET _analyze
{
"text":"Email me at [email protected]",
"tokenizer": "uax_url_email"
}
可配置項
max_token_length最大令牌長度,如果看到令牌超過此長度,則將其max_token_length間隔分割,默認為255
COPY{
"settings": {
"analysis": {
"analyzer": {
"my_english_analyzer": {
"type": "standard",
"max_token_length": 5
}
}
}
}
}
經典分詞器(Classic Tokenizer)
可對首字母縮寫詞,公司名稱,電子郵件地址和互聯網主機名進行特殊處理,但是,這些規則并不總是有效,并且此關鍵詞生成器不適用于英語以外的大多數其他語言
特點
- 它最多將標點符號拆分為單詞,洗掉標點符號,但是,不帶空格的點被認為是查詢關鍵詞的一部分
- 此分詞器可以將郵件地址和URL地址識別為查詢的term(詞條)
使用案例
原始內容
COPY"The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
測驗分詞
COPYGET _analyze
{
"text":"The 2 QUICK Brown-Foxes jumped over the lazy dog's bone.",
"analyzer": "classic"
}

可配置項
max_token_length最大令牌長度,如果看到令牌超過此長度,則將其max_token_length間隔分割,默認為255,
COPY{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "my_tokenizer"
}
},
"tokenizer": {
"my_tokenizer": {
"type": "classic",
"max_token_length": 5
}
}
}
}
}
結構化文本分詞
關鍵詞分詞器(Keyword Tokenizer)
它其實不做分詞處理,只是將輸入作為 Term 輸出
關鍵詞分詞器其實是執行了一個空操作的分析,它將任何輸入的文本作為一個單一的關鍵詞輸出,

使用案例
原始內容
COPY"In 2020, Java is the best language in the world."
測驗分詞
COPYGET _analyze
{
"text":"In 2020, Java is the best language in the world.",
"analyzer": "keyword"
}
會發現前后內容根本沒有發生改變,這也是這個分詞器的作用,有些時候我們針對一個需要分詞查詢的欄位進行查詢的時候,可能并不希望查詢條件被分詞,這個時候就可以使用這個分詞器,整個查詢條件作為一個關鍵詞使用

正則分詞器(Pattern Tokenizer)
模式標記器使用 Java正則運算式,使用JAVA的正則運算式進行詞語的拆分,
它可以通過正則運算式的方式進行分詞,默認是用 \W+ 進行分割的,也就是非字母的符合進行切分的,

使用案例
原始內容
COPY"In 2020, Java is the best language in the world."
測驗分詞
COPYGET _analyze
{
"text":"In 2020, Java is the best language in the world.",
"analyzer": "patter"
}

可配置項
正則分詞器有以下的選項
| 選項 | 描述 |
|---|---|
| pattern | 正則運算式 |
| flags | 正則運算式標識 |
| lowercase | 是否使用小寫詞匯 |
| stopwords | 停止詞的串列, |
| stopwords_path | 定義停止詞檔案的路徑, |
COPY{
"settings": {
"analysis": {
"analyzer": {
"my_email_analyzer": {
"type": "pattern",
"pattern": "\\W|_",
"lowercase": true
}
}
}
}
}
路徑分詞器(Path Tokenizer)
可以對檔案系統的路徑樣式的請求進行拆分,回傳被拆分各個層級內容,
使用案例
原始內容
COPY"/one/two/three"
測驗分詞
COPYGET _analyze
{
"text":"/one/two/three",
"tokenizer":"path_hierarchy"
}

可配置項
| 選項 | 描述 |
|---|---|
| delimiter | 用作路徑分隔符的字符 |
| replacement | 用于定界符的可選替換字符 |
| buffer_size | 單次讀取到術語緩沖區中的字符數,默認為1024,術語緩沖區將以該大小增長,直到所有文本都被消耗完為止,建議不要更改此設定, |
| reverse | 正向還是反向獲取關鍵詞 |
| skip | 要忽略的內容 |
COPY{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "my_tokenizer"
}
},
"tokenizer": {
"my_tokenizer": {
"type": "path_hierarchy",
"delimiter": "-",
"replacement": "/",
"skip": 2
}
}
}
}
}
語言分詞(Language Analyzer)
ES 為不同國家語言的輸入提供了
Language Analyzer分詞器,在里面可以指定不同的語言
支持語種
支持如下語種:
| 關鍵字 | 語種 |
|---|---|
| arabic | 美 /??r?b?k/ 阿拉伯語 |
| armenian | 美 /ɑ?r?mi?ni?n/ 亞美尼亞語 |
| basque | 美 /b?sk,bɑ?sk/ 巴斯克語 |
| bengali | 美 /be??ɡɑ?li/ 孟加拉語 |
| brazilian | 美 /br??z?li?n/ 巴西語 |
| bulgarian | 美 /b?l?ɡeri?n/ 保加利亞語 |
| catalan | 美 /?k?t?l?n/ 加泰羅尼亞語 |
| cjk | 中日韓統一表意文字 |
| czech | 美 /t?ek/ 捷克語 |
| danish | 美 /?de?n??/ 丹麥語 |
| dutch | 美 /d?t?/ 荷蘭語 |
| english | 美 /???ɡl??/ 英語 |
| estonian | 美 /e?sto?ni?n/ 愛沙尼亞語 |
| finnish | 美 /?f?n??/ 芬蘭語 |
| french | 美 /frent?/ 法語 |
| galician | 美 /ɡ??l??n/ 加里西亞語 |
| german | 美 /?d???rm?n/ 德語 |
| greek | 美 /ɡri?k/ 希臘語 |
| hindi | 美 /?h?ndi/ 北印度語 |
| hungarian | 美 /h???ɡeri?n/ 匈牙利語 |
| indonesian | 美 /??nd??ni??n/ 印度尼西亞語 |
| irish | 美 /?a?r??/ 愛爾蘭語 |
| italian | 美 /??t?li?n/ 意大利語 |
| latvian | 美 /?l?tvi?n/ 拉脫維亞語 |
| lithuanian | 美 /?l?θu?e?ni?n/ 立陶宛語 |
| norwegian | 美 /n??r?wi?d??n/ 挪威語 |
| persian | /‘p??r??n/ 波斯語 |
| portuguese | 美 /?p??rt???ɡi?z/ 葡萄牙語 |
| romanian | 美 /ro’men??n/ 羅馬尼亞語 |
| russian | 美 /?r??n/ 俄語 |
| sorani | 索拉尼語 |
| spanish | 美 /?sp?n??/ 西班牙語 |
| swedish | 美 /?swi?d??/ 瑞典語 |
| turkish | 美 /?t??rk??/ 土耳其語 |
| thai | 美 /ta?/ 泰語 |
使用案例
下面我們使用英語進行分析
原始內容
COPY"In 2020, Java is the best language in the world."
測驗分詞
COPYGET _analyze
{
"text":"In 2020, Java is the best language in the world.",
"analyzer":"english"
}
自定義分詞器
當內置的分詞器無法滿足需求時,可以創建
custom型別的分詞器,
配置引數
| 引數 | 描述 |
|---|---|
| tokenizer | 內置或定制的tokenizer.(必須) |
| char_filter | 內置或定制的char_filter(非必須) |
| filter | 內置或定制的token filter(非必須) |
| position_increment_gap | 當值為文本陣列時,設定改值會在文本的中間插入假空隙,設定該屬性,對與后面的查詢會有影響,默認該值為100. |
創建索引
上面的示例中定義了一個名為
my_custom_analyzer的分詞器
該分詞器的type為custom,tokenizer為standard,char_filter為hmtl_strip,filter定義了兩個分別為:lowercase和asciifolding
COPYPUT my_index
{
"settings": {
"analysis": {
"analyzer": {
"my_custom_analyzer":{
"type":"custom",
"tokenizer":"standard",
"char_filter":["html_strip"],
"filter":["lowercase","asciifolding"]
}
}
}
}
}
使用案例
原始內容
COPYIs this <b>déjà vu</b>?
測驗分詞
COPYPOST my_index/_analyze
{
"text": "Is this <b>déjà vu</b>?",
"analyzer": "my_custom_analyzer"
}
中文分詞器
IKAnalyzer
IKAnalyzer是一個開源的,基于java的語言開發的輕量級的中文分詞工具包
從2006年12月推出1.0版開始,IKAnalyzer已經推出了3個大版本,在 2012 版本中,IK 實作了簡單的分詞歧義排除演算法,標志著 IK 分詞器從單純的詞典分詞向模擬語意分詞衍化
使用IK分詞器
IK提供了兩個分詞演算法:
- ik_smart:最少切分,
- ik_max_word:最細粒度劃分,
ik_smart
使用案例
原始內容
COPY傳智教育的教學質量是杠杠的
測驗分詞
COPYGET _analyze
{
"analyzer": "ik_smart",
"text": "傳智教育的教學質量是杠杠的"
}
ik_max_word
使用案例
原始內容
COPY傳智教育的教學質量是杠杠的
測驗分詞
COPYGET _analyze
{
"analyzer": "ik_max_word",
"text": "傳智教育的教學質量是杠杠的"
}
自定義詞庫
我們在使用IK分詞器時會發現其實有時候分詞的效果也并不是我們所期待的
問題描述
例如我們輸入“傳智教育的教學質量是杠杠的”,但是分詞器會把“傳智教育”進行拆開,分為了“傳”,“智”,“教育”,但我們希望的是“傳智教育”可以不被拆開,
解決方案
對于以上的問題,我們只需要將自己要保留的詞,加到我們的分詞器的字典中即可
編輯字典內容
進入elasticsearch目錄
plugins/ik/config中,創建我們自己的字典檔案yixin.dic,并添加內容:
COPYcd plugins/ik/config
echo "傳智教育" > custom.dic
擴展字典
進入我們的elasticsearch目錄 :
plugins/ik/config,打開IKAnalyzer.cfg.xml檔案,進行如下配置:
COPYvi IKAnalyzer.cfg.xml
#增加如下內容
<entry key="ext_dict">custom.dic</entry>
再次測驗
重啟ElasticSearch,再次使用kibana測驗
COPYGET _analyze
{
"analyzer": "ik_max_word",
"text": "傳智教育的教學質量是杠杠的"
}
可以發現,現在我們的詞匯”傳智教育”就不會被拆開了,達到我們想要的效果了
本文由
傳智教育博學谷狂野架構師教研團隊發布,如果本文對您有幫助,歡迎
關注和點贊;如果您有任何建議也可留言評論或私信,您的支持是我堅持創作的動力,轉載請注明出處!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/551895.html
標籤:其他
上一篇:Scala學習總結(一)
下一篇:返回列表
