什么是分詞器
我們上一篇文章講過倒排索引,比如我們搜 明月 ,可能會根據倒排索引 查到靜夜思 這篇古詩,對吧,這里面的明月 低頭 月光 ,就是分詞器給我們分的詞,我的理解就是,我們通過分詞器給某篇文章打上了分詞的tag ,然后根據tag 可以找到對應的標題,比如 新手機 華為,如果沒有分詞的話,我們查找 新手機華為 可能 華為新手機 就不會被搜索到,因為順序的問題。
分詞器的組成
- character filter(字符過濾器)
在對一段文本分詞之前,要先清洗一遍原始數據吧,比如html標簽,什么加黑加粗加長加大中劃線下劃線啥的,其實我要的就是 里面的 一個詞,比如我是一個帥哥啊其實我只需要拿到 我很帥 三個字 給分詞器就行了 - 分詞器 就是 tokenizers
字符串過濾器把內容【我是一個帥哥啊】給分詞器,分詞器 就開始分詞,比如分成了
我
是
一個
帥哥
啊
但是這里面有一些詞并不是關鍵詞,你拿這個詞搜索也沒有意義,比如 你想搜 我感冒了怎么辦啊,為了讓搜索更高效,讓用戶看起來更專業,我們拿到的關鍵詞 應該是
感冒
怎么辦
而不是 怎么辦啊 或者啊,所以需要對分詞之后的結果再進行過濾,這個時候就要用到分詞過濾器
- token filers 就是 分詞過濾器,完成對無用詞的過濾
Elastic 默認支持九種不同的分詞模式
-
stardard(過濾標點符號)
在這里插入圖片描述 -
simple (過濾標點符號和數字,只剩下字母了)
在這里插入圖片描述 -
whitespace (空格分詞,不過濾內容)
在這里插入圖片描述 stop(過濾標點符號,數字,過濾語氣詞,停頓詞)
[圖片上傳失敗...(image-a8ee4f-1637325715209)]-
keyword (將內容作為一個整體,不做任何處理,所以這也是為什么keyword 用于精準匹配)
在這里插入圖片描述 -
patter(正則匹配,參考java的正則匹配規則)
在該栗子中,只過濾數字
在這里插入圖片描述 -
fingerprint(轉小寫 去重 過濾停止詞,排序)
在這里插入圖片描述 支持30多種常見語言的分詞器(沒有中文)
支持自定義分詞器
IK分詞器
- 此處我們再解釋一遍為什么要用分詞,如果不用分詞,我們其實也可以搜素,比如下面這個栗子,我搜索華為的時候,我愛中華的文檔也被搜索了出來,我顯然不是我要的,但是為什么會出現這種取情況呢?我們看中文返回的分詞是什么
我們發現es對漢字默認是單個拆分的,你搜索華為,本來搜索的是華為相關的條目,單個拆分之后 ,就會把包含華和為兩個字的都查找出來,這明顯不是我們想要的,所以我們需要分詞來達到更精準的匹配
ElasticSearch 對于英文分詞天生就有了,因為老外生來就用外語,那么中文怎么辦呢?IK分詞器在2006年推出了1.0版本。
IK Analyzer是一個開源的,基于java語言開發的輕量級的中文分詞工具包。被一個叫medcl(曾勇 elastic開發工程師與布道師,elasticsearch開源社區負責人,2015年加入elastic)的人集成到了elasticsearch中, 并支持自定義字。
IK分詞器的安裝github上面搜索https://github.com/medcl/elasticsearch-analysis-ik即可,注意版本一致,一定要去github 或者官方網站下載包,博主被第三方的包坑了兩三個小時裝過ik 分詞之后我們再查看
- 在這里插入圖片描述
-
但是,此時你搜索華為 是搜索不出來的,因為在創建文檔的時候就沒有 對 我愛華為 建立 華為的分詞索引,我們刪除重新創建
在這里插入圖片描述
搜索華為的時候 我愛中華 條目沒有出現,只找到了一條我愛華為,記住,文檔在創建的時候生成倒排索引,所以我們在創建文檔的時候最好是先 勾勒出來你需要的數據模型,根據模型選擇數據字段的類型,合適的分詞,有了合適的結構才會有合適的索引,有了合適的索引才會提供合適發服務。之前我見有朋友沒有mapping就插入數據,其實這個時候系統也動態生成了mapping ,但是這個maping 不一定符合你的要求。比如咱們剛才的分詞,你創建索引的時候就是 按照 單個字 創立的索引,那么這個時候你搜索 華為 作為一個詞去匹配,就會匹配不到。
[圖片上傳失敗...(image-a21413-1637325715209)]
IK分詞器的相關配置
- 我們看一下目錄
[elastic@localhost config]$ ls
extra_main.dic extra_single_word.dic extra_single_word_full.dic extra_single_word_low_freq.dic extra_stopword.dic IKAnalyzer.cfg.xml main.dic preposition.dic quantifier.dic stopword.dic suffix.dic surname.dic
[elastic@localhost config]$ pwd
/home/elastic/elasticsearch2/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">dic/hehe.dic;dic/haha.dic</entry>
<!--用戶可以在這里配置自己的擴展停止詞字典 比如 啊 呢 哦 無效詞 -->
<entry key="ext_stopwords">dic/stop.dic</entry>
<!--用戶可以在這里配置遠程擴展字典 配置自己的遠程擴展詞 -->
<entry key="remote_ext_dict">http://m.dic.cn/ext.txt</entry>
<!--用戶可以在這里配置遠程擴展停止詞字典-->
<!-- <entry key="remote_ext_stopwords">http://m.dic.cn/stop.txt</entry> -->
</properties>
- 這里可以簡單舉個栗子看一下,比如 香菇藍瘦,我們先來看一下
[圖片上傳失敗...(image-9bdf6d-1637325715209)] - 我現在來配置一下文件,使用遠程擴展詞庫(注意,如果修改或者新增了遠程詞庫的地址,則需要重啟,如果地址沒變,只是進行了補充,則無需重啟)
- 看一下我的遠程地址(注意,為了避免瀏覽器訪問txt 亂碼,在nginx的server里面加上
charset 'utf-8';
)
在這里插入圖片描述
我的配置文件如下,配置了一個遠程擴展詞典
<?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"></entry>
<!--用戶可以在這里配置自己的擴展停止詞字典-->
<entry key="ext_stopwords"></entry>
<!--用戶可以在這里配置遠程擴展字典 -->
<entry key="remote_ext_dict">https://0e2d-222-129-5-131.ngrok.io/ext.txt</entry>
<!--用戶可以在這里配置遠程擴展停止詞字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
-
我在遠程詞典添加一個詞 技術小蟲
在這里插入圖片描述
main.dic
ik原生內置的中文詞庫,總共有27萬多條,只要是這些單詞,都會被分在一起
quantifier.dic
放了一些單位相關的詞
suffix.dic
放了一些后綴
surname.dic
中國的姓氏
stopword.dic
英文停用詞