Elasticsearch之安裝ik分詞外掛
IK簡介
IK Analyzer是一個開源的,基於java語言開發的輕量級的中文分詞工具包。從2006年12月推出1.0版開始, IKAnalyzer已經推出了4個大版本。最初,它是以開源專案Luence為應用主體的,結合詞典分詞和文法分析演算法的中文分片語件。從3.0版本開 始,IK發展為面向Java的公用分片語件,獨立於Lucene專案,同時提供了對Lucene的預設優化實現。在2012版本中,IK實現了簡單的分詞 歧義排除演算法,標誌著IK分詞器從單純的詞典分詞向模擬語義分詞衍化。
IK Analyzer 2012特性:
- 採用了特有的“正向迭代最細粒度切分演算法“,支援細粒度和智慧分詞兩種切分模式;
- 在系統環境:Core2 i7 3.4G雙核,4G記憶體,window 7 64位, Sun JDK 1.6_29 64位 普通pc環境測試,IK2012具有160萬字/秒(3000KB/S)的高速處理能力。
- 2012版本的智慧分詞模式支援簡單的分詞排歧義處理和數量詞合併輸出。
- 採用了多子處理器分析模式,支援:英文字母、數字、中文詞彙等分詞處理,相容韓文、日文字元
- 優化的詞典儲存,更小的記憶體佔用。支援使用者詞典擴充套件定義。特別的,在2012版本,詞典支援中文,英文,數字混合詞語。
安裝
- 編譯打包
# 克隆遠端庫到本地
$ git clone https://github.com/medcl/elasticsearch-analysis-ik
$ cd elasticsearch-analysis-ik
# 檢視tag列表
$ git tag
# 檢出與elasticsearch版本相匹配的版本
$ git checkout tags/{version}
# 打包
$ mvn clean
$ mvn compile
$ mvn package
- 手動安裝
# 解壓到plugins/ik目錄
$ unzip target/releases/elasticsearch-analysis-ik-{version}.zip ES_HOME /plugins/ik
注意:
- ES_HOME為ES對應安裝目錄
- version為選擇的ik版本號
- 重啟elasticsearch
備註:
- ik_max_word: 會將文字做最細粒度的拆分,比如會將“中華人民共和國國歌”拆分為“中華人民共和國,中華人民,中華,華人,人民共和國,人民,人,民,共和國,共和,和,國國,國歌”,會窮盡各種可能的組合;
- ik_smart: 會做最粗粒度的拆分,比如會將“中華人民共和國國歌”拆分為“中華人民共和國,國歌”。
測試案例
- 建立索引
curl -XPUT http://localhost:9200 /index
- 建立mapping
curl -XPOST http://localhost:9200/index/fulltext/_mapping -d'
{
"fulltext": {
"_all": {
"analyzer": "ik_max_word",
"search_analyzer": "ik_max_word",
"term_vector": "no",
"store": "false"
},
"properties": {
"content": {
"type": "string",
"store": "no",
"term_vector": "with_positions_offsets",
"analyzer": "ik_max_word",
"search_analyzer": "ik_max_word",
"include_in_all": "true",
"boost": 8
}
}
}
}'
- 插入測試資料
curl -XPOST http://localhost:9200/index/fulltext/1 -d'
{"content":"美國留給伊拉克的是個爛攤子嗎"}
'
curl -XPOST http://localhost:9200/index/fulltext/2 -d'
{"content":"公安部:各地校車將享最高路權"}
'
curl -XPOST http://localhost:9200/index/fulltext/3 -d'
{"content":"中韓漁警衝突調查:韓警平均每天扣1艘中國漁船"}
'
curl -XPOST http://localhost:9200/index/fulltext/4 -d'
{"content":"中國駐洛杉磯領事館遭亞裔男子槍擊 嫌犯已自首"}
'
- 查詢並高亮關鍵詞
curl -XPOST http://localhost:9200/index/fulltext/_search -d'
{
"query" : { "term" : { "content" : "中國" }},
"highlight" : {
"pre_tags" : ["<tag1>", "<tag2>"],
"post_tags" : ["</tag1>", "</tag2>"],
"fields" : {
"content" : {}
}
}
}
'
返回結果
{
"took": 14,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 2,
"max_score": 2,
"hits": [
{
"_index": "index",
"_type": "fulltext",
"_id": "4",
"_score": 2,
"_source": {
"content": "中國駐洛杉磯領事館遭亞裔男子槍擊 嫌犯已自首"
},
"highlight": {
"content": [
"<tag1>中國</tag1>駐洛杉磯領事館遭亞裔男子槍擊 嫌犯已自首 "
]
}
},
{
"_index": "index",
"_type": "fulltext",
"_id": "3",
"_score": 2,
"_source": {
"content": "中韓漁警衝突調查:韓警平均每天扣1艘中國漁船"
},
"highlight": {
"content": [
"均每天扣1艘<tag1>中國</tag1>漁船 "
]
}
}
]
}
}
IK配置說明
plugins/elasticsearch-analysis-ik-*/config/ik/IKAnalyzer.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 擴充套件配置</comment>
<!--使用者可以在這裡配置自己的擴充套件字典 -->
<entry key="ext_dict">custom/mydict.dic;custom/single_word_low_freq.dic</entry>
<!--使用者可以在這裡配置自己的擴充套件停止詞字典-->
<entry key="ext_stopwords">custom/ext_stopword.dic</entry>
<!--使用者可以在這裡配置遠端擴充套件字典 -->
<entry key="remote_ext_dict">location</entry>
<!--使用者可以在這裡配置遠端擴充套件停止詞字典-->
<entry key="remote_ext_stopwords">http://xxx.com/xxx.dic</entry>
</properties>
熱更新 IK 分詞使用方法
目前該外掛支援熱更新 IK 分詞,通過上文在 IK 配置檔案中提到的如下配置
<!--使用者可以在這裡配置遠端擴充套件字典 -->
<entry key="remote_ext_dict">location</entry>
<!--使用者可以在這裡配置遠端擴充套件停止詞字典-->
<entry key="remote_ext_stopwords">location</entry>
其中 location
是指一個 url,比如 http://yoursite.com/getCustomDict
,該請求只需滿足以下兩點即可完成分詞熱更新。
該 http 請求需要返回兩個頭部(header),一個是
Last-Modified
,一個是ETag
,這兩者都是字串型別,只要有一個發生變化,該外掛就會去抓取新的分詞進而更新詞庫。該 http 請求返回的內容格式是一行一個分詞,換行符用
\n
即可。
滿足上面兩點要求就可以實現熱更新分詞了,不需要重啟 ES 例項。
可以將需自動更新的熱詞放在一個 UTF-8 編碼的 .txt 檔案裡,放在 nginx 或其他簡易 http server 下,當 .txt 檔案修改時,http server 會在客戶端請求該檔案時自動返回相應的 Last-Modified 和 ETag。可以另外做一個工具來從業務系統提取相關詞彙,並更新這個 .txt 檔案。
常見問題
自定義詞典為什麼沒有生效?
請確保你的擴充套件詞典的文字格式為 UTF8 編碼
設定elasticsearch預設分詞為ik:在
ES_HOME/config/elasticsearch.yml
檔案最後一行中增加index.analysis.analyzer.default.type: ik
即可。