Elasticsearch 搜索引擎內置了很多種分詞器,但是對中文分詞
不友好,所以我們需要藉助第三方中文分詞工具包。
悟空哥專門研究了下 ik
中文分詞工具包該怎麼玩,希望對大家有所幫助。
本文主要內容如下:
1 ES 中的分詞的原理
1.1 ES 的分詞器概念
ES 的一個分詞器 ( tokenizer ) 接收一個字符流,將其分割爲獨立的詞元 ( tokens ) ,然後輸出詞元流。
ES 提供了很多內置的分詞器,可以用來構建自定義分詞器 ( custom ananlyzers )
1.2 標準分詞器原理
比如 stadard tokenizer 標準分詞器,遇到空格進行分詞。該分詞器還負責記錄各個詞條 ( term ) 的順序或 position 位置 ( 用於 phrase 短語和 word proximity 詞近鄰查詢 ) 。每個單詞的字符偏移量 ( 用於高亮顯示搜索的內容 ) 。
1.3 英文和標點符號分詞示例
查詢示例如下:
POST _analyze
{
"analyzer": "standard",
"text": "Do you know why I want to study ELK? 2 3 33..."
}
查詢結果:
do, you, know, why, i, want, to, study, elk, 2,3,33
從查詢結果可以看到:
(1)標點符號沒有分詞。
(2)數字會進行分詞。
1.4 中文分詞示例
但是這種分詞器對中文的分詞支持不友好,會將詞語分詞爲單獨的漢字。比如下面的示例會將 悟空聊架構
分詞爲 悟
,空
,聊
,架
,構
,期望分詞爲 悟空
,聊
,架構
。
POST _analyze
{
"analyzer": "standard",
"text": "悟空聊架構"
}
我們可以安裝 ik 分詞器來更加友好的支持中文分詞。
2 安裝 ik 分詞器
2.1 ik 分詞器地址
ik 分詞器地址:
https://github.com/medcl/elasticsearch-analysis-ik/releases
先檢查 ES 版本,我安裝的版本是 7.4.2
,所以我們安裝 ik 分詞器的版本也選擇 7.4.2
http://192.168.56.10:9200/
{
"name" : "8448ec5f3312",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "xC72O3nKSjWavYZ-EPt9Gw",
"version" : {
"number" : "7.4.2",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "2f90bbf7b93631e52bafb59b3b049cb44ec25e96",
"build_date" : "2019-10-28T20:40:44.881551Z",
"build_snapshot" : false,
"lucene_version" : "8.2.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
2.2 安裝 ik 分詞器的方式
2.2.1 方式一:容器內安裝 ik 分詞器
- 進入 es 容器內部 plugins 目錄
docker exec -it <容器 id> /bin/bash
- 獲取 ik 分詞器壓縮包
wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.4.2/elasticsearch-analysis-ik-7.4.2.zip
- 解壓縮 ik 壓縮包
unzip 壓縮包
- 刪除下載的壓縮包
rm -rf *.zip
2.2.2 方式二:映射文件安裝 ik 分詞器
進入到映射文件夾
cd /mydata/elasticsearch/plugins
下載安裝包
wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.4.2/elasticsearch-analysis-ik-7.4.2.zip
- 解壓縮 ik 壓縮包
unzip 壓縮包
- 刪除下載的壓縮包
rm -rf *.zip
2.2.3 方式三:Xftp 上傳壓縮包到映射目錄
先用 XShell 工具連接虛擬機 ( 操作步驟可以參考之前寫的文章 02. 快速搭建 Linux 環境-運維必備) ,然後用 Xftp 將下載好的安裝包複製到虛擬機。
3 解壓 ik 分詞器到容器中
- 如果沒有安裝 unzip 解壓工具,則安裝 unzip 解壓工具。
apt install unzip
- 解壓 ik 分詞器到當前目錄的 ik 文件夾下。
命令格式:unzip <ik 分詞器壓縮包>
實例:
unzip ELK-IKv7.4.2.zip -d ./ik
- 修改文件夾權限爲可讀可寫。
chmod -R 777 ik/
- 刪除 ik 分詞器壓縮包
rm ELK-IKv7.4.2.zip
4 檢查 ik 分詞器安裝
- 進入到容器中
docker exec -it <容器 id> /bin/bash
- 查看 Elasticsearch 的插件
elasticsearch-plugin list
結果如下,說明 ik 分詞器安裝好了。是不是很簡單。
ik
然後退出 Elasticsearch 容器,並重啓 Elasticsearch 容器
exit
docker restart elasticsearch
5 使用 ik 中文分詞器
ik 分詞器有兩種模式
-
智能分詞模式 ( ik_smart )
-
最大組合分詞模式 ( ik_max_word )
我們先看下 智能分詞
模式的效果。比如對於 一顆小星星
進行中文分詞,得到的兩個詞語:一顆
、小星星
我們在 Dev Tools Console 輸入如下查詢
POST _analyze
{
"analyzer": "ik_smart",
"text": "一顆小星星"
}
得到如下結果,被分詞爲 一顆和小星星。
再來看下 最大組合分詞模式
。輸入如下查詢語句。
POST _analyze
{
"analyzer": "ik_max_word",
"text": "一顆小星星"
}
一顆小星星
被分成了 6 個詞語:一顆、一、顆、小星星、小星、星星。
我們再來看下另外一箇中文分詞。比如搜索悟空哥聊架構,期望結果:悟空哥、聊、架構三個詞語。
實際結果:悟、空哥、聊、架構四個詞語。ik 分詞器將悟空哥分詞了,認爲 空哥
是一個詞語。所以需要讓 ik 分詞器知道 悟空哥
是一個詞語,不需要拆分。那怎麼辦做呢?
6 自定義分詞詞庫
6.1 自定義詞庫的方案
-
方案
新建一個詞庫文件,然後在 ik 分詞器的配置文件中指定分詞詞庫文件的路徑。可以指定本地路徑,也可以指定遠程服務器文件路徑。這裏我們使用遠程服務器文件的方案,因爲這種方案可以支持熱更新 ( 更新服務器文件,ik 分詞詞庫也會重新加載 ) 。
-
修改配置文件
ik 分詞器的配置文件在容器中的路徑:
/usr/share/elasticsearch/plugins/ik/config/IKAnalyzer.cfg.xml。
修改這個文件可以通過修改映射文件,文件路徑:
/mydata/elasticsearch/plugins/ik/config/IKAnalyzer.cfg.xml
編輯配置文件:
vim /mydata/elasticsearch/plugins/ik/config/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>
修改配置 remote_ext_dict
的屬性值,指定一個 遠程網站文件的路徑,比如 http://www.aaa.aaa/ikwords.text。
這裏我們可以自己搭建一套 nginx 環境,然後把 ikwords.text 放到 nginx 根目錄。
6.2 搭建 nginx 環境
方案:首先獲取 nginx 鏡像,然後啓動一個 nginx 容器,然後將 nginx 的配置文件拷貝到根目錄,再刪除原 nginx 容器,再用映射文件夾的方式來重新啓動 nginx 容器。
- 通過 docker 容器安裝 nginx 環境。
docker run -p 80:80 --name nginx -d nginx:1.10
- 拷貝 nginx 容器的配置文件到 mydata 目錄的 conf 文件夾
cd /mydata
docker container cp nginx:/etc/nginx ./conf
- mydata 目錄 裏面創建 nginx 目錄
mkdir nginx
- 移動 conf 文件夾到 nginx 映射文件夾
mv conf nginx/
- 終止並刪除原 nginx 容器
docker stop nginx
docker rm <容器 id>
- 啓動新的容器
docker run -p 80:80 --name nginx \
-v /mydata/nginx/html:/usr/share/nginx/html \
-v /mydata/nginx/logs:/var/log/nginx \
-v /mydata/nginx/conf:/etc/nginx \
-d nginx:1.10
- 訪問 nginx 服務
192.168.56.10
報 403 Forbidden, nginx/1.10.3 則表示 nginx 服務正常啓動。403 異常的原因是 nginx 服務下沒有文件。
- nginx 目錄新建一個 html 文件
cd /mydata/nginx/html
vim index.html
hello passjava
-
再次訪問 nginx 服務
瀏覽器打印 hello passjava。說明訪問 nginx 服務的頁面沒有問題。
-
創建 ik 分詞詞庫文件
cd /mydata/nginx/html
mkdir ik
cd ik
vim ik.txt
填寫 悟空哥
,並保存文件。
- 訪問詞庫文件
http://192.168.56.10/ik/ik.txt
瀏覽器會輸出一串亂碼,可以先忽略亂碼問題。說明詞庫文件可以訪問到。
- 修改 ik 分詞器配置
cd /mydata/elasticsearch/plugins/ik/config
vim IKAnalyzer.cfg.xml
- 重啓 elasticsearch 容器並設置每次重啓機器後都啓動 elasticsearch 容器。
docker restart elasticsearch
docker update elasticsearch --restart=always
- 再次查詢分詞結果
可以看到 悟空哥聊架構
被拆分爲 悟空哥
、聊
、架構
三個詞語,說明自定義詞庫中的 悟空哥
有作用。
寫了兩本 PDF,回覆 分佈式 或 PDF 下載。
我的 JVM 專欄已上架,回覆 JVM 領取。
個人網站:www.passjava.cn