一個elasticsearch 中文分詞插件。
QQ交流群:743457803
如何開發ES分詞外掛請參考這裡
主要參考了IK 和HanLP
支援複雜漢字,有的漢字在java中長度不是1 ,例如?
,而IK
等不支援。
支援單字分詞和搜索,而ik_max_word
模式不支援。
支援自訂長度分詞,適合短文本下的人名等識別。
根據空格標點符號字母數字等分隔後的漢字文字長度
<=autoWordLength
會自動辨識為一個字詞。
支援emoji搜尋
相比IK,比IK更智能,更準確。
ik_max_word
是窮舉所有可能詞,導致搜尋一些不相關的也會被搜到。任性冲动过
詞結果居然有任性性冲动动过
,那麼搜性冲动
就會把這個doc搜尋到。南京市长江大桥
,結果是南京市市长长江大桥
,那麼搜市长
會把這個doc搜尋到,而hao分詞器不會,透過詞頻計算最短路,辨識出可能性最高的詞組。還可以依照自己場景,隨意調節詞頻。ik_smart 分詞結果不是ik_max_word 的子集,hao_search_mode 分詞結果是hao_index_mode 分詞結果的子集
相比HanLp,比HanLP更輕量,分詞更可控,沒有一些智能的人名等預測功能,可能會導致分詞不穩定不準確,機器學習對於長短文本不同,預測分詞結果也不同。而HanLP也沒有官方的ES插件。
根據詞頻計算最短路,窮舉出可能的詞,而不是所有的詞,如果窮舉的詞不對,可以調詞頻來糾正,詞頻文件是可讀性更好的txt
文件
支持元詞,例如俄罗斯
不會再拆分成俄
和罗斯
(罗斯
是常用人名)。這樣搜罗斯
就不會把俄罗斯
相關文件召回
但是不支持詞性
提供Analyzer: hao_search_mode
, hao_index_mode
Tokenizer: hao_search_mode
, hao_index_mode
Git tag | ES version |
---|---|
master | ES最新穩定版 |
v7.17.1 | 7.17.1 |
vX.YZ | XYZ |
方式1. bin/elasticsearch-plugin install file:///Users/xiaoming/Download/analysis-hao.zip
方式2. 解壓縮後,放在es plugins目錄即可,保證是如下目錄結構{ES_HOME}/plugins/analysis-hao/(各种jar等文件)
,同時目錄不能有zip文件
最後重啟ES
如果沒有你需要的對應ES版本,要修改幾個地方:
pom.xml
-> elasticsearch.version
的值為對應版本。HaoTokenizerFactory.java
的構造方法。 最後執行mvn clean package -Dmaven.test.skip=true
,就可以得到插件的zip
安裝套件。以下是自訂分詞器可用的設定項
配置項參數 | 功能 | 預設值 |
---|---|---|
enableIndexMode | 是否使用index模式,index模式為細顆粒度。 | hao_search_mode 為false , hao_index_mode 為true ,細顆粒度適合Term Query,粗顆粒度適合Phrase查詢 |
enableFallBack | 若分詞報錯,是否啟動最細粒度分詞,即按字分。建議search_mode 使用,不至於影響使用者搜尋。 index_mode 不啟動,以便及報錯告警通知。 | false 不啟動降級 |
enableFailDingMsg | 是否啟動失敗釘子通知,通知位址為HttpAnalyzer.cfg.xml 的dingWebHookUrl 欄位。 | false |
enableSingleWord | 是否使用細粒度傳回的單字。例如体力值 ,分詞結果只存体力值 ,体力 ,而不存值 | false |
autoWordLength | 根據空格標點符號字母數字等分隔後的漢字文字長度小於autoWordLength 會自動辨識為一個字詞。 預設-1不開啟, >=2視為開啟 | -1 |
hao_index_mode
會根據詞庫的詞條和權重,遞歸分詞,直到該詞不可分。如果設定了enableSingleWord=true
,會一直分到單字為止。
例如這段文本南京市长江大桥
南京市长江大桥
==>南京市
,长江大桥
南京市
==>南京
,市
,长江大桥
==>长江
,大桥
enableSingleWord=false
,遞歸停止,得到分詞為南京市
,南京
,市
,长江大桥
,长江
,大桥
enableSingleWord=true
,繼續遞歸,直到單字位置,得到分詞為南京市
,南京
,南
,京
,市
,长江大桥
,长江
,长
,江
,大桥
,大
,桥
hao_search_mode
此模式下,相當於hao_index_mode
模式只會遞歸一次。 分詞結果為南京市
,长江大桥
。因為該模式下enableIndexMode=false
,如果改成true
,則和hao_index_mode
一樣的效果。
參數 | 功能 | 備註 |
---|---|---|
baseDictionary | 基礎詞庫檔名 | 放在插件config 目錄或es的config 目錄,不用更改 |
customerDictionaryFile | 使用者自訂遠端詞庫文件,多個文件以英文分號;分隔 | 會儲存在插件config 目錄或es的config 目錄 |
remoteFreqDict | 遠端使用者自訂詞庫文件 | 方便熱更新,熱更新透過下面兩個參數定時更新。 |
syncDicTime | 遠端詞庫下次同步時間hh:mm:ss | 不填使用syncDicPeriodTime 作為下次同步時間 |
syncDicPeriodTime | 遠端詞庫同步時間間隔,秒,最小值30 | 例如syncDicTime=20:00:00,syncDicPeriodTime=86400 ,則是每天20點同步 |
dingWebHookUrl | 釘釘機器人url | 用於分詞異常,同步詞庫異常/成功通知 |
dingMsgContent | 機器人通知文案 | 注意配置釘釘機器人的時候關鍵字要跟這個文案匹配,不然會訊息發送失敗 |
優先讀取
{ES_HOME}/config/analysis-hao/
目錄,沒有讀取{ES_HOME}/plugins/analysis-hao/config
目錄下的文件
base_dictionary.txt
,以逗號分割,後面的數字表示詞頻。 例如:奋发图强
分詞結果是奋
,发图
,强
, 是因為发图
這個詞的詞頻太高了(因為出現次數高),則可以降低詞頻,手動修改base_dictionary.txt
文件就好了。customerDictionaryFile
。 遠端詞庫的檔案格式每行格式為{词},{词频},{是否元词}
, 例如俄罗斯,1000,1
。 是否元詞字段解釋: 1
代表是元詞,不會再細拆分,俄罗斯
不會再拆分成俄
和罗斯
(羅斯是常用人名)。這樣搜罗斯
就不會召回俄罗斯
相關文件。 0
就是可以繼續細拆分,例如奋发图强
建索引:
PUT test/
{
"settings": {
"index": {
"analysis": {
"analyzer": {
"search_analyzer": {
"filter": [
"lowercase"
],
"char_filter": [
"html_strip"
],
"type": "custom",
"tokenizer": "my_search_token"
},
"index_analyzer": {
"filter": [
"lowercase"
],
"char_filter": [
"html_strip"
],
"type": "custom",
"tokenizer": "my_index_token"
}
},
"tokenizer": {
"my_index_token": {
"enableFailDingMsg": "true",
"type": "hao_index_mode",
"enableSingleWord": "true",
"enableFallBack": "true",
"autoWordLength": 3
},
"my_search_token": {
"enableFailDingMsg": "true",
"type": "hao_search_mode",
"enableSingleWord": "true",
"enableFallBack": "true",
"autoWordLength": 3
}
}
},
"number_of_replicas": "0"
}
},
"mappings": {
"properties": {
"title": {
"type": "text",
"index_options": "offsets",
"analyzer": "index_analyzer",
"search_analyzer": "search_analyzer"
}
}
}
}
測試分詞
test/_analyze
{
"analyzer": "index_analyzer",
"text": "徐庆年 奋发图强打篮球有利于提高人民生活,有的放矢,中华人民共和国家庭宣传委员会宣。?"
}
test/_analyze
{
"analyzer": "search_analyzer",
"text": "徐庆年 奋发图强打篮球有利于提高人民生活,有的放矢,中华人民共和国家庭宣传委员会宣。?"
}
徐庆年
並不在詞庫中,但透過autoWordLength
辨識為一個字。