ES學習——分析器和自定義分析器
簡介
es在對文件進行倒排索引的需要用分析器(Analyzer)對文件進行分析、建立索引。從文件中提取詞元(Token)的演算法稱為分詞器(Tokenizer),在分詞前預處理的演算法稱為字元過濾器(Character Filter),進一步處理詞元的演算法稱為詞元過濾器(Token Filter),最後得到詞(Term)。這整個分析演算法稱為分析器(Analyzer)。
其工作流程:
- 先會使用字元過濾器
CharacterFilters
對文件中的不需要的字元過濾(例如html語言的<br/>等等) - 用
Tokenizer
分詞器大段的文字分成詞(Tokens)(例如可以空格基準對一句話進行分詞) - 最後用
TokenFilter
在對分完詞的Tokens進行過濾、處理(比如除去英文常用的量詞:a,the,或者把去掉英文複數等)
我們可以使用_analyze
來看es的分詞是不是符合我們的預期目標,我們使用預設的分析器對下面這句話進行分析。結果包括token,起始的偏移量,型別和序號。我目前先只關注token即可。
GET /jindouwin_search_group/_analyze
{
"text": "Her(5) a Black-cats"
}
結果:
"tokens": [ { "token": "her", "start_offset": 0, "end_offset": 3, "type": "<ALPHANUM>", "position": 0 }, { "token": "5", "start_offset": 4, "end_offset": 5, "type": "<NUM>", "position": 1 }, { "token": "a", "start_offset": 7, "end_offset": 8, "type": "<ALPHANUM>", "position": 2 }, { "token": "black", "start_offset": 9, "end_offset": 14, "type": "<ALPHANUM>", "position": 3 }, { "token": "cats", "start_offset": 15, "end_offset": 19, "type": "<ALPHANUM>", "position": 4 } ] }
從結果看出,分詞器先去掉了一些無用的符號,再把一句話分為Her、5、a、Black、cats,在用TokenFilter
過濾大小寫。
分析器
es中除了standard
標準分析器外,還有english
、stop
、lower
等等。我們來看下使用english分析器來解析同一句話的效果。
GET /jindouwin_search_group/_analyze { "text": "Her(5) a Black-cats" , "analyzer": "english" } 結果: { { "tokens": [ { "token": "her", "start_offset": 0, "end_offset": 3, "type": "<ALPHANUM>", "position": 0 }, { "token": "5", "start_offset": 4, "end_offset": 5, "type": "<NUM>", "position": 1 }, { "token": "black", "start_offset": 9, "end_offset": 14, "type": "<ALPHANUM>", "position": 3 }, { "token": "cat", "start_offset": 15, "end_offset": 19, "type": "<ALPHANUM>", "position": 4 } ] } }
可以明顯的看出,english去掉了一些常用詞(a),和把cats的複數形式去掉了。
當然es的強大之處在於除了內建的分詞器之外,我們可以自定義分析器,通過組裝CharacterFilters、Tokenizer、TokenFilter三個不同元件來自定義分析器或者可以使用別人完成的分析器,最出名的就是ik
中文分詞外掛。
除此之外我們也可以CharacterFilters、Tokenizer、TokenFilter進行自定義。
關於一些內建的分析器種類,這裡不一一分析,大家可以在官網進行翻閱。
自定義分析器
官網示例:
作為示範,讓我們一起來建立一個自定義分析器吧,這個分析器可以做到下面的這些事:
- 使用 html清除 字元過濾器移除HTML部分。
- 使用一個自定義的 對映 字元過濾器把 & 替換為 " and " :
"char_filter": {
"&_to_and": {
"type": "mapping",
"mappings": [ "&=> and "]
}
}
- 使用 標準 分詞器分詞。
- 小寫詞條,使用 小寫 詞過濾器處理。
- 使用自定義 停止 詞過濾器移除自定義的停止詞列表中包含的詞:
"filter": {
"my_stopwords": {
"type": "stop",
"stopwords": [ "the", "a" ]
}
}
我們的分析器定義用我們之前已經設定好的自定義過濾器組合了已經定義好的分詞器和過濾器:
"analyzer": {
"my_analyzer": {
"type": "custom",
"char_filter": [ "html_strip", "&_to_and" ],
"tokenizer": "standard",
"filter": [ "lowercase", "my_stopwords" ]
}
}
彙總起來,完整的 建立索引 請求 看起來應該像這樣:
PUT /my_index
{
"settings": {
"analysis": {
"char_filter": {
"&_to_and": {
"type": "mapping",
"mappings": [ "&=> and "]
}},
"filter": {
"my_stopwords": {
"type": "stop",
"stopwords": [ "the", "a" ]
}},
"analyzer": {
"my_analyzer": {
"type": "custom",
"char_filter": [ "html_strip", "&_to_and" ],
"tokenizer": "standard",
"filter": [ "lowercase", "my_stopwords" ]
}}
}}}
索引被建立以後,使用 analyze API 來 測試這個新的分析器:
GET /my_index1/_analyze
{
"analyzer":"my_analyzer",
"text": "The quick & brown fox"
}
拷貝為 CURL在 SENSE 中檢視
下面的縮略結果展示出我們的分析器正在正確地執行:
{
"tokens": [
{
"token": "quick",
"start_offset": 4,
"end_offset": 9,
"type": "<ALPHANUM>",
"position": 1
},
{
"token": "and",
"start_offset": 10,
"end_offset": 11,
"type": "<ALPHANUM>",
"position": 2
},
{
"token": "brown",
"start_offset": 12,
"end_offset": 17,
"type": "<ALPHANUM>",
"position": 3
},
{
"token": "fox",
"start_offset": 18,
"end_offset": 21,
"type": "<ALPHANUM>",
"position": 4
}
]
}
這個分析器現在是沒有多大用處的,除非我們告訴 Elasticsearch在哪裡用上它。我們可以像下面這樣把這個分析器應用在一個 string 欄位上:
PUT /my_index/_mapping/my_type
{
"properties": {
"title": {
"type": "string",
"analyzer": "my_analyzer"
}
}
}