[教學] Elasticsearch 安裝與支援繁體中文分詞

之前有介紹一個全文檢索程式 Meilisearch,不過目前還無法適用於中大型應用系統以及功能較少,而Elasticsearch 是目前最多人使用的全文檢索引擎,不只用於文字檢索還會用於地圖坐標運算及其他應用,並且能夠自己做多樣化的設定,而 Elasticsearch 本身並不支援中文,所以需要自行安裝分詞器,而現在多人在維護的分詞都是簡體中文的,本篇文章將教學如何安裝 Elasticsearch 並且支援繁體中文分詞

官方網站:https://www.elastic.co/

原始碼:https://github.com/elastic/elasticsearch

安裝 Elasticsearch

首先第一個步驟是安裝 Elasticsearch,這邊需要注意 Elasticsearch 要下載的版本

因為對應版本的外掛只能適用於對應版本的 Elasticsearch,為了方便 (省去自己手動編譯) 可以選擇有已經編譯好外掛的版本來安裝

舉例現在的 Elasticsearch 最新的是 8.3.3,但是目前 IK Analyzer 只有 8.2.3 那可以選擇下載 8.2.3 的 Elasticsearch

Elasticsearch 下載點連結:https://www.elastic.co/downloads/past-releases#elasticsearch

選擇下載對應作業系統的版本

下載後解壓縮後直接執行 binarry 就能啟動

./bin/elasticsearch

第一次啟動的時候會取得:

  • 帳號密碼:用來登入的
  • kibana 的 enrollment token:後面步驟用來給 kibana 連結認證用的

伺服器會啟動在:https://0.0.0.0:9200

安裝 kibana

kibana 下載連結:https://www.elastic.co/downloads/past-releases#kibana

選擇系統對應的版本與下載

下載後解壓縮直接執行 binarry 就能啟動

預設網頁會啟動在 http://localhost:5601

並且在第一次啟動會取得一個連結用來設定 elasticseach

將剛剛取得的 enrollment token 貼進去

稍微等一下就能進入登入畫面

輸入剛剛取得的帳號密碼就可以開始使用 kibana

安裝 IK 分析器

目前我們能找到有在維護的 Analyzer 分別都是簡體中文的,我們使用此簡體中文版本加一些設定來做到支援繁體中文

IK Analyzer 下載點:https://github.com/medcl/elasticsearch-analysis-ik/releases

下載後將解壓縮得到的資料夾放到 elasticsearch 中的 plugins 之中

重啟伺服器便完成安裝

可以進行測試一下,是否有支援簡體中文的文字

GET _analyze
{
  "analyzer": "ik_smart",
  "text": "传说中的厨具"
}
{
  "tokens" : [
    {
      "token" : "传说中",
      "start_offset" : 0,
      "end_offset" : 3,
      "type" : "CN_WORD",
      "position" : 0
    },
    {
      "token" : "的",
      "start_offset" : 3,
      "end_offset" : 4,
      "type" : "CN_CHAR",
      "position" : 1
    },
    {
      "token" : "厨具",
      "start_offset" : 4,
      "end_offset" : 6,
      "type" : "CN_WORD",
      "position" : 2
    }
  ]
}

設定支援繁體中文

支援繁體中文有兩個方式

方法一、直接修改 KL Analyzer 分詞內容,用工具轉成繁體中文並且加進分詞檔案

方法二、使用轉簡轉換 STConvert Analysis,先將輸入的繁體轉成簡體,再接 KL Analyzer 來分詞

方法一、直接修改 KL Analyzer 分詞內容

目前會分開的詞語是放在外掛資料夾中的 config/*.dic

使用文字編輯器開啟可以看到裡面有很多的詞語,使用工具將其轉換成繁體就可以了

這邊可以使用 opencc 轉換工具,下載點與安裝教學:https://github.com/BYVoid/OpenCC/wiki/Download

這樣使用指令將所有 dic 檔案內容補上繁體中文就可以:

opencc -c s2tw.json -i main.dic -o /tmp/main-zhtw.dic
cp main.dic /tmp/main-zhcn.dic
cat /tmp/main-zhtw.dic /tmp/main-zhcn.dic | sort | uniq > main.dic

重啟伺服器測試看看

GET _analyze
{
  "analyzer": "ik_smart",
  "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" : 6,
      "end_offset" : 8,
      "type" : "CN_WORD",
      "position" : 2
    },
    {
      "token" : "實現",
      "start_offset" : 8,
      "end_offset" : 10,
      "type" : "CN_WORD",
      "position" : 3
    },
    {
      "token" : "動態",
      "start_offset" : 10,
      "end_offset" : 12,
      "type" : "CN_WORD",
      "position" : 4
    },
    {
      "token" : "替換",
      "start_offset" : 12,
      "end_offset" : 14,
      "type" : "CN_WORD",
      "position" : 5
    }
  ]
}

方法二、使用轉簡轉換 STConvert Analysis

STConvert Analysis 下載點:https://github.com/medcl/elasticsearch-analysis-stconvert

下載後將解壓縮得到的資料夾放到 elasticsearch 中的 plugins 之中

重啟伺服器便完成安裝


接著要對指定的 index 進行設定「自定義分析器」

簡單來說分析器 (analysis) 是由 char_filter、tokenizer、filter 三個步驟來完成的,這邊設定是做到的步驟是:

step 1. 將文字轉成簡體
step 2. 使用 ik 分詞器將簡體中文語句進行分詞
step 3. 將分完的詞轉為繁體

PS: 詳細運作說明可以參考:https://www.elastic.co/guide/cn/elasticsearch/guide/current/custom-analyzers.html

PUT /product/_settings
{
  "analysis": {
    "char_filter": {
      "stconvert": {
        "type": "stconvert",
        "delimiter": "#",
        "keep_both": false,
        "convert_type": "t2s"
      }
    },
    "tokenizer": {
      "ik_smart": {
        "type": "ik_smart"
      }
    },
    "filter": {
      "stconvert": {
        "type": "stconvert",
        "delimiter": "#",
        "keep_both": false,
        "convert_type": "s2t"
      }
    },
    "analyzer": {
      "my_chinese_analyzer": {
        "type": "custom",
        "char_filter": ["stconvert"],
        "tokenizer": "ik_smart",
        "filter": ["stconvert"]
      }
    }
  }
}

此時可以測試看看 ik 與 stconvert 一起運作的結果, 會取得簡體中文的分詞結果

GET product/_analyze
{
  "analyzer" : "my_chinese_analyzer",
  "text" : "傳說中的廚具"
}
{
  "tokens" : [
    {
      "token" : "傳説中",
      "start_offset" : 0,
      "end_offset" : 3,
      "type" : "CN_WORD",
      "position" : 0
    },
    {
      "token" : "的",
      "start_offset" : 3,
      "end_offset" : 4,
      "type" : "CN_CHAR",
      "position" : 1
    },
    {
      "token" : "廚具",
      "start_offset" : 4,
      "end_offset" : 6,
      "type" : "CN_WORD",
      "position" : 2
    }
  ]
}

接著就可以在指定的欄位使用要的分詞器

PUT /product/_mapping
{
  "properties": {
    "title": {
      "type": "text",
      "analyzer": "my_chinese_analyzer"
    }
  }
}

或是直接設定整個 index 全欄位使用相同分詞器

(將上面的自訂分詞器的 my_chinese_analyzer 直接改成 default)

POST /product/_close

PUT /product/_settings
{
  "analysis": {
    "char_filter": {
      "stconvert": {
        "type": "stconvert",
        "delimiter": "#",
        "keep_both": false,
        "convert_type": "t2s"
      }
    },
    "tokenizer": {
      "ik_smart": {
        "type": "ik_smart"
      }
    },
    "filter": {
      "stconvert": {
        "type": "stconvert",
        "delimiter": "#",
        "keep_both": false,
        "convert_type": "s2t"
      }
    },
    "analyzer": {
      "default": {
        "type": "custom",
        "char_filter": [
          "stconvert"
        ],
        "tokenizer": "ik_smart",
        "filter": [
          "stconvert"
        ]
      }
    }
  }
}

POST /product/_open

發表迴響