[ES]elasticsearch章5 ES的分詞(二)
Elasticsearch 中文搜索時遇到幾個問題:
- 當搜索關鍵詞如:“人民幣”時,如果分詞將“人民幣”分成“人”,“民”,“幣”三個單字,那麽搜索該關鍵詞會匹配到很多包含該單字的無關內容,但是如果將該詞分詞成一個整詞“人民幣”,搜索單字如“人”字又不會匹配到包含“人民幣”關鍵詞的內容,怎麽解決這個問題,既保證覆蓋度又保證準確度?
- 搜索“RMB”時只會匹配到包含“RMB”關鍵詞的內容,實際上,“RMB”和“人民幣”是同義詞,我們希望用戶搜索“RMB”和“人民幣”可以相互匹配,ES同義詞怎麽配置?
接下來從以下幾點講一下怎麽ES中文分詞
- 中文分詞器
- ES 分詞流程之 analysis,analyzer,filter,tokenizer
- ES內置分詞器
- 自定義analyzer
- ES同義詞功能實現
1.IK 分詞器
- 1,Elasticsearch中文分詞我們采用Ik分詞,ik有兩種分詞模式,ik_max_word,和ik_smart模式;
- ik_max_word 和 ik_smart 什麽區別?
ik_max_word: 會將文本做最細粒度的拆分,比如會將“中華人民共和國國歌”拆分為“中華人民共和國,中華人民,中華,華人,人民共和國,人民,人,民,共和國,共和,和,國國,國歌”,會窮盡各種可能的組合;
ik_smart: 會做最粗粒度的拆分,比如會將“中華人民共和國國歌”拆分為“中華人民共和國,國歌”。
索引時,為了提供索引的覆蓋範圍,通常會采用ik_max_word分析器,會以最細粒度分詞索引,搜索時為了提高搜索準確度,會采用ik_smart分析器,會以粗粒度分詞
字段mapping設置如下:
"author": {
"type": "string",
"analyzer": "ik",
"search_analyzer": "ik_smart"
}
2.Elasticsearch之分析(analysis)和分析器(analyzer)
analysis索引分析模塊充當analyzer分析器的可配置註冊表,通過analyzer對文檔索引階段的字段和搜索String進行處理,自定義analyzer時,通常需要character filter tokenizer token filters來完成
2.1 character filter 字符過濾器
首先字符串經過過濾器(character filter),他們的工作是在分詞前處理字符串。字符過濾器能夠去除HTML標記,例如把“<a>”變成“a
2.2 tokenizer 分詞器
英文分詞可以根據空格將單詞分開,中文分詞比較復雜,可以采用機器學習算法來分詞
2.2 token filters 表征過濾器
最後,每個詞都通過所有表征過濾(token filters),他可以修改詞(例如將“Quick”轉為小寫),去掉詞(例如停用詞像“a”、“and”、“the”等等),或者增加詞(例如同義詞像“a”、“and”、“the”等等)或者增加詞(例如同義詞像“jump”和“leap”)。
2.3 ES分詞流程
character filter-->>tokenizer-->>token filters
2.5 自定義analyzer
官網example:
index :
analysis :
analyzer :
myAnalyzer2 :
type : custom
tokenizer : myTokenizer1
filter : [myTokenFilter1, myTokenFilter2]
char_filter : [my_html]
position_increment_gap: 256
tokenizer :
myTokenizer1 :
type : standard
max_token_length : 900
filter :
myTokenFilter1 :
type : stop
stopwords : [stop1, stop2, stop3, stop4]
myTokenFilter2 :
type : length
min : 0
max : 2000
char_filter :
my_html :
type : html_strip
escaped_tags : [xxx, yyy]
read_ahead : 1024
2.6 分詞mapping設置
通常為了保證索引時覆蓋度和搜索時準確度,索引分詞器采用ik_max_word,搜索分析器采用ik_smart模式
"content": {
"type": "string",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
}
1.7 如果更改了mapping分詞器,需要重新索引數據才能生效
POST /_reindex
{
"source": {
"index": "twitter"
},
"dest": {
"index": "new_twitter"
}
}
因為倒排索引中的數據是索引時由分詞器來處理的,如果分詞器有變化,那麽搜索時query關鍵詞即使和doc中關鍵詞相同,但是因為分詞器的原因,分出來的詞會出現不匹配的情況,因此當mapping或者分詞器字典同義詞詞典等發生變化時,需要reindex索引數據
1.8 更改別名,不重啟服務切換索引
POST /_aliases
{
"actions": [
{
"remove": {
"index": "oldindex",
"alias": "alias_oldindex"
}
},
{
"add": {
"index": "newindex",
"alias": "alias_oldindex"
}
}
]
}
2 同義詞
2.1 建議同義詞詞典
- elasticsearch /config/analysis 下建議同義詞詞典文件pro_synonym.txt,采用UTF-8編碼,寫入內容
- 同義詞內容格式 ,註意標點符號使用英文符號
- 啟航 => 起航 : "=>"左邊的詞全部會被右邊的詞替換
- 啟航,起航 :使用","英文逗號分隔,兩個詞是互等的,分詞時會同時分成兩個詞進行索引或者檢索,如"啟航"會被分成"啟航","起航"兩個詞分別建立索引或者去倒排索引檢索
自定義添加同義詞通過ik分詞器
"settings": {
"analysis": {
"filter": {
"my_synonym_filter": {
"type": "synonym",
"synonyms_path": "analysis/pro_synonym.txt"
}
},
"analyzer": {
"ik_syno_max_word": {
"tokenizer": "ik",
"filter": "my_synonym_filter"
},
"ik_syno_smart": {
"tokenizer": "ik_smart",
"filter": "my_synonym_filter"
}
}
}
}
想查看同義詞效果或者測試分詞效果
3 Suggest分詞
suggest詞需要對拼音前綴,全拼,中文進行前綴匹配,例如:“百度”一詞,鍵入"baidu","bd","百"都必須匹配到,因此在索引的時候需要一詞分多個分詞器來索引保存,中文采用單字分詞,拼音首字母和全拼需要自定義analyzer來索引。
- Elasticsearch Suggest setting mapping設置參考如下
{
"mappings": {
"suggest": {
"properties": {
"full_pinyin": {
"type": "completion",
"analyzer": "full_pinyin_analyzer",
"payloads": true,
"preserve_separators": false,
"preserve_position_increments": true,
"max_input_length": 50
},
"prefix_pinyin": {
"type": "completion",
"analyzer": "prefix_pinyin_analyzer",
"search_analyzer": "standard",
"payloads": true,
"preserve_separators": false,
"preserve_position_increments": true,
"max_input_length": 50
},
"suggestText": {
"type": "completion",
"analyzer": "standard",
"payloads": true,
"preserve_separators": false,
"preserve_position_increments": true,
"max_input_length": 50
}
}
}
},
"settings": {
"index": {
"analysis": {
"filter": {
"_pattern": {
"type": "pattern_capture",
"preserve_original": "1",
"patterns": ["([0-9])", "([a-z])"]
},
"full_pinyin": {
"keep_first_letter": "false",
"keep_none_chinese_in_first_letter": "false",
"type": "pinyin",
"keep_original": "false",
"keep_full_pinyin": "true"
},
"prefix_pinyin": {
"keep_first_letter": "true",
"none_chinese_pinyin_tokenize": "false",
"type": "pinyin",
"keep_original": "false",
"keep_full_pinyin": "false"
}
},
"analyzer": {
"full_pinyin_analyzer": {
"filter": ["lowercase", "full_pinyin"],
"tokenizer": "standard"
},
"prefix_pinyin_analyzer": {
"filter": ["lowercase", "prefix_pinyin"],
"tokenizer": "standard"
}
}
}
}
}
}
關於搜索關鍵詞會將不相關詞搜索出來
- 解決單字搜索的一種方案
- 問題:搜索時,搜索牙膏,需檢索出包含“牙膏”二字的內容,過濾掉包含“牙”或者“膏”的內容,但是搜索單字“牙”或者“膏”時需要將牙膏匹配出來
- 方案:加入單字字典,ik_max_word分詞時,會把所有形式分出來,因此單字字典,此分詞模式下會將單字索引起來,ik_smart會按照最粗粒度分詞,搜索關鍵詞時不會匹配單字內容
- 索引和搜索采用不同分詞器 "analyzer": "ik", "search_analyzer": "ik_smart"
- 過程:更改mapping,searchAnalyzer=ik_smart
[ES]elasticsearch章5 ES的分詞(二)