ElasticSearch中文分詞

一、基本概念

當一個文檔被存儲時,ES會使用分詞器從文檔中提取出若干詞元(token)來支持索引的存儲和搜索。
ES內置了很多分詞器,但內置的分詞器對中文的處理不好。下面通過例子來看內置分詞器的處理。在web客戶端發起如下的一個REST請求,對英文語句進行分詞:

POST http://localhost:9200/_analyze
{  
    "text": "hello world"  
}

操作成功後,響應的內容如下:

{
  "tokens": [
    {
      "token": "hello",
      "start_offset": 0,
      "end_offset": 5,
      "type": "<ALPHANUM>",
      "position": 0
    },
    {
      "token": "world",
      "start_offset": 6,
      "end_offset": 11,
      "type": "<ALPHANUM>",
      "position": 1
    }
  ]
}

上面結果顯示 "hello world"語句被分爲兩個單詞,因爲英文天生以空格分隔,自然就以空格來分詞,這沒有任何問題。

下面我們看一箇中文的語句例子,請求REST如下:

POST http://localhost:9200/_analyze
{  
    "text": "世界如此之大"  
}

操作成功後,響應的內容如下:

{
  "tokens": [
    {
      "token": "世",
      "start_offset": 0,
      "end_offset": 1,
      "type": "<IDEOGRAPHIC>",
      "position": 0
    },
    {
      "token": "界",
      "start_offset": 1,
      "end_offset": 2,
      "type": "<IDEOGRAPHIC>",
      "position": 1
    },
    {
      "token": "如",
      "start_offset": 2,
      "end_offset": 3,
      "type": "<IDEOGRAPHIC>",
      "position": 2
    },
    {
      "token": "此",
      "start_offset": 3,
      "end_offset": 4,
      "type": "<IDEOGRAPHIC>",
      "position": 3
    },
    {
      "token": "之",
      "start_offset": 4,
      "end_offset": 5,
      "type": "<IDEOGRAPHIC>",
      "position": 4
    },
    {
      "token": "大",
      "start_offset": 5,
      "end_offset": 6,
      "type": "<IDEOGRAPHIC>",
      "position": 5
    }
  ]
}
從結果可以看出,這種分詞把每個漢字都獨立分開來了,這對中文分詞就沒有意義了,所以ES默認的分詞器對中文處理是有問題的。好在有很多不錯的第三方的中文分詞器,可以很好地和ES結合起來使用。在ES中,每種分詞器(包括內置的、第三方的)都會有個名稱。上面默認的操作,其實用的分詞器的名稱是standard。下面的請求與前面介紹的請求是等價的,如:
POST http://localhost:9200/_analyze
{  
    "analyzer": "standard",
    "text": "世界如此之大"  
}
當我們換一個分詞器處理分詞時,只需將"analyzer"字段設置相應的分詞器名稱即可。
ES通過安裝插件的方式來支持第三方分詞器,對於第三方的中文分詞器,比較常用的是中科院ICTCLAS的smartcn和IKAnanlyzer分詞器。在本文中,我們介紹IKAnanlyzer分詞器(下面簡稱ik)的使用。

二、ik分詞器的安裝

ES提供了一個腳本elasticsearch-plugin(windows下爲elasticsearch-plugin.bat)來安裝插件,腳本位於ES安裝目錄的bin目錄下。elasticsearch-plugin腳本可以有三種命令,靠參數區分:

1、 elasticsearch-plugin install 插件地址
install 參數指定的命令是安裝指定的插件到當前ES節點中。

2、 elasticsearch-plugin list
list參數指定的命令是顯示當前ES節點已經安裝的插件列表。

3、 elasticsearch-plugin remove 插件名稱
remove 參數指定的命令是刪除已安裝的插件。

使用elasticsearch-plugin install 安裝插件時,插件地址既可以是一個遠程文件地址(在線安裝),也可以是下載到本地的文件,不管是遠程文件或本地文件,對於ik插件來說都是一個zip文件。
注意,ik的版本要與ES的版本一致,因爲本文ES用的是7.8.0版本,所以我們ik也用的是7.8.0版本。

遠程文件安裝命令如下:

./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.8.0/elasticsearch-analysis-ik-7.8.0.zip

如果不能下載,也可以從本地文件安裝,elasticsearch-plugin install後面跟的路徑,如果是本地的話,需要帶file:///協議頭

linux下的本地安裝命令是:

./bin/elasticsearch-plugin install file:///home/hadoop/elasticsearch-analysis-ik-7.8.0.zip

windows下本地安裝的命令是:

elasticsearch-plugin.bat install file:///D:/hadoop/elasticsearch-analysis-ik-7.8.0.zip

安裝完畢後,發現在ES的安裝目錄下的plugins目錄下多了一個analysis-ik目錄(內容是ik的zip包解壓後根目錄下的所有文件,一共是5個jar文件和1個properties配置文件),另外ES的安裝目錄下的config目錄下多了一個analysis-ik目錄(內容是ik的zip包解壓後根目錄下的config目錄下所有文件,用於放置ik的自定義詞庫)。

如果要使用插件,需要重啓es.

新版本的ik提供了兩個分詞器,分別是ik_max_word 和ik_smart

三、ik中文分詞器的使用

輸入命令如下:

POST http://localhost:9200/_analyze
{  
    "analyzer": "ik_max_word",
    "text": "世界如此之大"  
}

響應結果如下:

{
  "tokens": [
    {
      "token": "世界",
      "start_offset": 0,
      "end_offset": 2,
      "type": "CN_WORD",
      "position": 0
    },
    {
      "token": "如此之",
      "start_offset": 2,
      "end_offset": 5,
      "type": "CN_WORD",
      "position": 1
    },
    {
      "token": "如此",
      "start_offset": 2,
      "end_offset": 4,
      "type": "CN_WORD",
      "position": 2
    },
    {
      "token": "之大",
      "start_offset": 4,
      "end_offset": 6,
      "type": "CN_WORD",
      "position": 3
    }
  ]
}

再測試ik_smart,輸入命令如下:

POST http://localhost:9200/_analyze
{  
    "analyzer": "ik_smart",
    "text": "世界如此之大"  
}

響應結果如下:

{
  "tokens": [
    {
      "token": "世界",
      "start_offset": 0,
      "end_offset": 2,
      "type": "CN_WORD",
      "position": 0
    },
    {
      "token": "如此",
      "start_offset": 2,
      "end_offset": 4,
      "type": "CN_WORD",
      "position": 1
    },
    {
      "token": "之大",
      "start_offset": 4,
      "end_offset": 6,
      "type": "CN_WORD",
      "position": 2
    }
  ]
}

比較兩個分詞器對同一句中文的分詞結果,ik_max_word比ik_smart得到的中文詞更多(從兩者的英文名含義就可看出來),但這樣也帶來一個問題,使用ik_max_word會佔用更多的存儲空間。

四、ik的自定義詞典

有時,可能ik自身提供的分詞詞典無法滿足特定的一些需求(如專用名詞等),ik提供了自定義詞典的功能,也就是用戶可以自己定義一些詞彙,這樣ik就會把它們當作詞典中的內容來處理。

舉個例子,對於上面例子中的“世界如此之大”這個中文語句,ik詞庫中不會有“界如此”這樣一個單詞,假設“界如此”就是一個專用名詞,我們希望ik能識別出來。這時就可自定義ik的詞典。具體方法是:

1、新建擴展名爲dic的文本文件,文件中寫入想增加的詞條,每個詞條單獨一行,如文件名是test.dic,文件內容如下:

界如此
高潛

上面例子中有兩個自定義詞條。

2、將上面的dic文件保存到ES安裝目錄的config目錄下的analysis-ik目錄(安裝ik插件時產生的目錄)下,可以建立子目錄,放在子目錄下。比如文件的路徑如:
** config/analysis-ik/mydic/test.dic**

3、修改ik的配置文件IKAnalyzer.cfg.xml(位於config/analysis-ik目錄下),在配置文件中增加如下條目:

<entry key="ext_dict">mydict/test.dic</entry>

這樣就將自定義的字典文件加到ik的字典中了。

4、重啓ES讓生效。

這時我們發起如下的REST請求:

POST http://localhost:9200/_analyze
{  
    "analyzer": "ik_max_word",
    "text": "世界如此之大"  
}

響應結果如下:

{
  "tokens": [
    {
      "token": "世界",
      "start_offset": 0,
      "end_offset": 2,
      "type": "CN_WORD",
      "position": 0
    },
    {
      "token": "界如此",
      "start_offset": 1,
      "end_offset": 4,
      "type": "CN_WORD",
      "position": 1
    },
    {
      "token": "如此之",
      "start_offset": 2,
      "end_offset": 5,
      "type": "CN_WORD",
      "position": 2
    },
    {
      "token": "如此",
      "start_offset": 2,
      "end_offset": 4,
      "type": "CN_WORD",
      "position": 3
    },
    {
      "token": "之大",
      "start_offset": 4,
      "end_offset": 6,
      "type": "CN_WORD",
      "position": 4
    }
  ]
}

可以看出,自定義的“界如此”詞條被分詞出來了。不過如果我們將analyzer改爲ik_smart卻發現“界如此”詞條沒能被識別出來。

轉載 https://www.jianshu.com/p/bb89ad7a7f7d

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章