Elasticsearch 分詞器是什麼?

Elasticsearch Analyzer 分詞器是什麼,以及日語搜尋 token filter 簡介

Analysis 是 Elasticsearch 的一個概念,他可以將我們數據 寫入及查詢時,也會針對分詞做處理。

這些 analysis 的概念主要是由 Analyzer(分詞器) 來處理,主要做的事情包含:

Elasticsearch 內建包含 Alalyzer 可以透過過濾、變形、分詞方式把字句拆分成可以搜尋的索引,基本構成如下:

  • Character filter: 可以將文字過濾,例如將文本的 HTML 內容進行過濾
  • Tokenizer: 按照規則進行分詞處理,一個 analyzer 只需有一個 Tokenizer
  • Token Filter: 將 Tokenizer 分詞進階處理,例如去掉一些詞語或轉換大小寫會類型

在 Elasticsearch 內置的分詞器包含:

分詞器名稱 處理方式
standard analyzer 預設分詞器,可以做分詞切分,小寫處理
simple analyzer 按照符號切分(非字母),小寫處理
stop analyzer 小寫處理,停用詞語過濾(the, a, this…)
whitespace analyzer 依照空白進行切分,小寫處理,並且不會過濾HTML
keyword analyzer 不分詞,直接輸入
pattern analyzer 正則表達式,預設使用 \W+(非字符串分隔)

在了解分詞的運作方式之後,接下來我們就針對這些分詞器來進行範例演練:

standard analyzer

預設分詞器:

GET _analyze
{
  "analyzer": "standard",
  "text":"hello for 2 <b>in your</b> why-not?"
}

處理結果,可以看到所有字串都會進行拆分,如下:

{
  "tokens" : [
    {
      "token" : "hello",
      "start_offset" : 0,
      "end_offset" : 5,
      "type" : "<ALPHANUM>",
      "position" : 0
    },
    {
      "token" : "for",
      "start_offset" : 6,
      "end_offset" : 9,
      "type" : "<ALPHANUM>",
      "position" : 1
    },
    {
      "token" : "2",
      "start_offset" : 10,
      "end_offset" : 11,
      "type" : "<NUM>",
      "position" : 2
    },
    {
      "token" : "b",
      "start_offset" : 13,
      "end_offset" : 14,
      "type" : "<ALPHANUM>",
      "position" : 3
    },
    {
      "token" : "in",
      "start_offset" : 15,
      "end_offset" : 17,
      "type" : "<ALPHANUM>",
      "position" : 4
    },
    {
      "token" : "your",
      "start_offset" : 18,
      "end_offset" : 22,
      "type" : "<ALPHANUM>",
      "position" : 5
    },
    {
      "token" : "b",
      "start_offset" : 24,
      "end_offset" : 25,
      "type" : "<ALPHANUM>",
      "position" : 6
    },
    {
      "token" : "why",
      "start_offset" : 27,
      "end_offset" : 30,
      "type" : "<ALPHANUM>",
      "position" : 7
    },
    {
      "token" : "not",
      "start_offset" : 31,
      "end_offset" : 34,
      "type" : "<ALPHANUM>",
      "position" : 8
    }
  ]
}

simple analyzer

按照符號切分(非字母),小寫處理:

GET _analyze
{
  "analyzer": "standard",
  "text":"hello for 2 <b>in your</b> why-not?"
}

處理結果,可以看到數字已經消失,如下:

{
  "tokens" : [
    {
      "token" : "hello",
      "start_offset" : 0,
      "end_offset" : 5,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "for",
      "start_offset" : 6,
      "end_offset" : 9,
      "type" : "word",
      "position" : 1
    },
    {
      "token" : "b",
      "start_offset" : 13,
      "end_offset" : 14,
      "type" : "word",
      "position" : 2
    },
    {
      "token" : "in",
      "start_offset" : 15,
      "end_offset" : 17,
      "type" : "word",
      "position" : 3
    },
    {
      "token" : "your",
      "start_offset" : 18,
      "end_offset" : 22,
      "type" : "word",
      "position" : 4
    },
    {
      "token" : "b",
      "start_offset" : 24,
      "end_offset" : 25,
      "type" : "word",
      "position" : 5
    },
    {
      "token" : "why",
      "start_offset" : 27,
      "end_offset" : 30,
      "type" : "word",
      "position" : 6
    },
    {
      "token" : "not",
      "start_offset" : 31,
      "end_offset" : 34,
      "type" : "word",
      "position" : 7
    }
  ]
}

接下來以下幾項僅舉例,可以自行試試看:

stop analyzer

小寫處理,停用詞語過濾(the, a, this…)

GET _analyze
{
  "analyzer": "stop",
  "text":"hello for 2 <b>in your</b> why-not?"
}

whitespace analyzer

依照空白進行切分,小寫處理 ,並且不會過濾HTML

GET _analyze
{
  "analyzer": "whitespace",
  "text":"hello for 2 <b>in your</b> why-not?"
}

keyword analyzer

不分詞,直接輸入

GET _analyze
{
  "analyzer": "keyword",
  "text":"hello for 2 <b>in your</b> why-not?"
}

輸出結果

{
  "tokens" : [
    {
      "token" : "hello for 2 <b>in your</b> why-not?",
      "start_offset" : 0,
      "end_offset" : 35,
      "type" : "word",
      "position" : 0
    }
  ]
}

pattern analyzer

正則表達式,預設使用 \W+(非字符串分隔)

GET _analyze
{
  "analyzer": "pattern",
  "text":"hello for 2 <b>in your</b> why-not?"
}

日語搜尋

日語包含多音詞與拼寫方式

  • 平假名, 如「検索 -> けんさく」
  • 片假名全形,如 「検索 -> ケンサク」
  • 片假名半形,如「検索 -> ケンサク」
  • 漢字,如 「検索」
  • 羅馬字全形,如「検索 -> kennsaku」
  • 羅馬字半形,如「検索 -> kennsaku」

上述提到的多種型態,因此在搜尋時,需要使用自行定義的 analyzer

簡易入門

  • Kuromoji
  • Sudachi 進階
  • MeCab
  • Juman++

在這裡先介紹 Kuromoji 如何處理日語

Kuromoji 的 token filter 介紹:

一個 Kuromoji token filter 的如下

PUT my_index { "mappings": { "my_type": { "properties": { "title": { "type": "text", "analyzer": "kuromoji" } } } } }

等同於

PUT my_index { "settings": { "analysis": { "analyzer": { "ja_fulltext_analyzer": { "type": "custom", "tokenizer": "kuromoji_tokenizer", "filter": [ "cjk_width", "lowercase", "kuromoji_stemmer", "ja_stop", "kuromoji_part_of_speech", "kuromoji_baseform" ] } } } }, "mappings": { "my_type": { "properties": { "title": { "type": "text", "analyzer": "ja_fulltext_analyzer" } } } } }

底下個別說明各個 token filter 的功能:

Lowercase token filteredit

將英文轉小寫

CJK Width Token Filter

將 ASCII 全形字元轉為半形

ja_stop Token Filter

日本停止詞過濾

kuromoji_baseform token filter

日語詞根過濾

kuromoji_readingform Token Filter

日語讀音過濾,把單詞轉換為發音,發音可以是片假名或羅馬字 2 種形式

kuromoji_part_of_speech Token Filter

日本語氣詞過濾

kuromoji_stemmer Token Filter

日本音長過濾,可去除單詞尾端的長音

kuromoji_number Token Filter

將漢語數字轉為 ASCII 數字