1. 程式人生 > >ES[7.6.x]學習筆記(七)IK中文分詞器

ES[7.6.x]學習筆記(七)IK中文分詞器

在上一節中,我們給大家介紹了ES的分析器,我相信大家對ES的全文搜尋已經有了深刻的印象。分析器包含3個部分:字元過濾器、分詞器、分詞過濾器。在上一節的例子,大家發現了,都是英文的例子,是吧?因為ES是外國人寫的嘛,中國如果要在這方面趕上來,還是需要螢幕前的小夥伴們的~ 英文呢,我們可以按照空格將一句話、一篇文章進行分詞,然後對分詞進行過濾,最後留下有意義的詞。但是中文怎麼分呢?中文的一句話是沒有空格的,這就要有一個強大的中文詞庫,當你的內容中出現這個詞時,就會將這個詞提煉出來。這裡大家也不用重複造輪子,經過前輩的努力,這個中文的分詞器已經有了,它就是今天要給大家介紹的**IK中文分詞器**。 ## IK中文分詞器的安裝 ES預設是沒有IK中文分詞器的,我們要將IK中文分詞器作為一個外掛安裝到ES中,安裝的步驟也很簡單: 1. 從GitHub上下載適合自己ES版本的IK中文分詞器,地址如下:`https://github.com/medcl/elasticsearch-analysis-ik/releases`。 2. 在我們的ES的外掛目錄中(`${ES_HOME}/plugins`)建立`ik`目錄, ```shell mkdir ik ``` 3. 將我們下載好的IK分詞器解壓到`ik`目錄,這裡我們安裝`unzip`命令,進行解壓。 4. 重啟我們所有的ES服務。 到這裡,我們的IK中文分詞器就安裝完了。 ## IK中文分詞器初探 在上一節我們訪問了ES的分析器介面,指定了分析器和文字的內容,我們就可以看到分詞的結果。那麼既然我們已經安裝了Ik中文分詞器,當然要看一下效果了。在看效果之前,我們先要說一下,IK中文分詞器外掛給我們提供了**兩個分析器**。 * ik_max_word: 會將文字做最細粒度的拆分 * ik_smart:會做最粗粒度的拆分 我們先看看`ik_max_word`的分析效果吧, ```shell POST _analyze { "analyzer": "ik_max_word", "text": "中華人民共和國國歌" } ``` 我們指定分詞器為`ik_max_word`,文字內容為`中華人民共和國國歌`。我們看一下分詞的結果: ```json { "tokens": [ { "token": "中華人民共和國", "start_offset": 0, "end_offset": 7, "type": "CN_WORD", "position": 0 }, { "token": "中華人民", "start_offset": 0, "end_offset": 4, "type": "CN_WORD", "position": 1 }, { "token": "中華", "start_offset": 0, "end_offset": 2, "type": "CN_WORD", "position": 2 }, { "token": "華人", "start_offset": 1, "end_offset": 3, "type": "CN_WORD", "position": 3 }, { "token": "人民共和國", "start_offset": 2, "end_offset": 7, "type": "CN_WORD", "position": 4 }, { "token": "人民", "start_offset": 2, "end_offset": 4, "type": "CN_WORD", "position": 5 }, { "token": "共和國", "start_offset": 4, "end_offset": 7, "type": "CN_WORD", "position": 6 }, { "token": "共和", "start_offset": 4, "end_offset": 6, "type": "CN_WORD", "position": 7 }, { "token": "國", "start_offset": 6, "end_offset": 7, "type": "CN_CHAR", "position": 8 }, { "token": "國歌", "start_offset": 7, "end_offset": 9, "type": "CN_WORD", "position": 9 } ] } ``` 我們可以看到,分詞分的非常細,我們在使用上面的這些進行搜尋時,都可以搜尋到`中華人民共和國國歌`這個文字。我們再看一下另外一個分析器`ik_smart`, ```shell POST _analyze { "analyzer": "ik_smart", "text": "中華人民共和國國歌" } ``` 我們的文字內容同樣是`中華人民共和國國歌`,看一下分詞的效果, ```json { "tokens": [ { "token": "中華人民共和國", "start_offset": 0, "end_offset": 7, "type": "CN_WORD", "position": 0 }, { "token": "國歌", "start_offset": 7, "end_offset": 9, "type": "CN_WORD", "position": 1 } ] } ``` 同樣的文字,使用`ik_smart`進行分詞時,只分成了兩個詞,和`ik_max_word`分詞器比少了很多。這就是兩個分詞器的區別,不過這兩個分析器都是可以對中文進行分詞的。 ## 建立索引時指定IK分詞器 既然我們安裝了IK中文分詞器的外掛,那麼我們在建立索引時就可以為`text`型別的欄位指定IK中文分詞器了。來看看下面的例子, ```shell PUT ik_index { "mappings": { "properties": { "id": { "type": "long" }, "title": { "type": "text", "analyzer": "ik_max_word" } } } } ``` 我們建立了索引`ik_index`,並且為欄位`title`指定了分詞器`ik_max_word`。我們執行一下,建立成功。然後我們再通過`GET`請求看一下這個索引的對映情況。 ```shell GET ik_index/_mapping ``` 返回的結果如下: ```json { "ik_index": { "mappings": { "properties": { "id": { "type": "long" }, "title": { "type": "text", "analyzer": "ik_max_word" } } } } } ``` 我們可以看到`title`欄位的分析器是`ik_max_word`。 ## 為索引指定預設IK分詞器 在上一節中,我們已經給大家介紹了為索引指定預設分詞器的方法,這裡我們直接把分詞器改為IK分詞器就可以了,如下: ```shell PUT ik_index { "settings": { "analysis": { "analyzer": { "default": { "type": "ik_max_word" } } } } } ``` 這樣我們在索引中就不用建立每一個欄位,可以通過動態欄位對映,將`String`型別的欄位對映為`text`型別,同時分詞器指定為`ik_max_word`。我們試一下,向`ik_index`索引中新增一條記錄。 ```shell POST ik_index/_doc/1 { "id": 1, "title": "大興龐各莊的西瓜", "desc": "大興龐各莊的西瓜真是好吃,脆沙瓤,甜掉牙" } ``` 執行成功。我們再執行搜尋試一下,如下: ```shell POST ik_index/_search { "query": { "match": { "title": "西瓜" } } } ``` 我們搜尋`title`欄位匹配`西瓜`,執行結果如下: ```json { "took": 2, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 1, "relation": "eq" }, "max_score": 0.2876821, "hits": [ { "_index": "ik_index", "_type": "_doc", "_id": "1", "_score": 0.2876821, "_source": { "id": 1, "title": "大興龐各莊的西瓜", "desc": "大興龐各莊的西瓜真是好吃,脆沙瓤,甜掉牙" } } ] } } ``` 我們可以看到剛才插入的那條記錄已經搜尋出來了,看來我們的IK中文分詞器起作用了,而且搜尋的結果也符合我們的預期。我們再看看搜尋`西`一個字的時候,能不能搜尋到結果, ```shell POST ik_index/_search { "query": { "match": { "title": "西" } } } ``` 執行結果如下: ```json { "took": 4, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 0, "relation": "eq" }, "max_score": null, "hits": [] } } ``` 並沒有搜尋出結果,說明在進行分詞時,`西瓜`是作為一個詞出現的,並沒有拆分成每一個字,這也是符合我們預期的。 好了~ 這一節的IK中文分詞器就給大家介紹到這