読者です 読者をやめる 読者になる 読者になる

Carpe Diem

備忘録。https://github.com/jun06t

Elasticsearchでの文字列の正規化

概要

検索システムを扱う上で文字列の正規化は非常に重要な要素です。
大抵納品されるデータはフォーマットがバラバラ(全角半角、カタカナひらがなが統一されないなど)なので、この正規化によってある程度統一させることで検索の精度を向上できます。

環境

  • Elasticsearch 2.3

NFC、NFD、NFKC、NFKD

Unicode正規化形式は主に4つあります。簡単にまとめると以下です。

名称 説明 具体例
NFC 正規分解して合成 「か」+「゛」→「が」
NFD 正規分解して分解 「が」→「か」+「゛」
NFKC 互換分解して合成 NFCと大体同じ。さらに「㌢」→「センチ」と展開
NFKD 互換分解して分解 NFDと大体同じ。さらに「㌢」→「センチ」と展開

解析フロー

Elasticsearchの文字列の解析は以下の順で行われます。特にchar_filtertoken_filterの順番に気をつけてください。

input => Character Filters => Tokenizer => Token Filters => output

icu_nomalizer

char_filterの1つです。Elasticsearchではtoken_filterとしても提供されてます。

前述のUnicode正規化をする際に使います。全角半角を統一してくれたり、濁点や半濁点に関しても統一してくれます。

設定例

{
  "settings": {
    "index": {
      "analysis": {
        "analyzer": {
          "nfkc_cf_normalized": { 
            "tokenizer": "icu_tokenizer",
            "char_filter": [
              "icu_normalizer"
            ]
          },
          "nfd_normalized": { 
            "tokenizer": "icu_tokenizer",
            "char_filter": [
              "nfd_normalizer"
            ]
          }
        },
        "char_filter": {
          "nfd_normalizer": {
            "type": "icu_normalizer",
            "name": "nfc",
            "mode": "decompose"
          }
        }
      }
    }
  }
}

namemodeに関しては以下があります。

オプション名 設定値
name nfc, nfkc, nfkc_cf
mode compose, decompose

先ほどのNFCやNFKCとの組み合わせは以下です。

name mode 正規化方法
nfc compose NFC
nfc decompose NFD
nfkc compose NFKC
nfkc decompose NFKD

nfkc_cfはNFKCの正規化に加えて大文字小文字統制もやってくれます。たとえば「A」なら「a」にしてくれます。

icu_folding

token_filterの1つです。

先ほどのicu_nomalizerは「åäöÅÄÖ」といったラテン語などの特殊な文字がそのままになります。
しかし検索時にこんな文字を入力してくれるユーザはいないので、「a」や「o」に変換する必要があります。
ただしデメリットとして「ー」の伸ばし棒や「゛゜」といった濁点なども消えてしまいます。
つまり「テーマ」→「テマ」や「がっこう」→「かっこう」になります。

設定例

{
  "settings": {
    "index": {
      "analysis": {
        "analyzer": {
          "folded": {
            "tokenizer": "icu_tokenizer",
            "filter": [
              "icu_folding"
            ]
          }
        }
      }
    }
  }
}

asciifolding

token_filterの1つです。

先ほどのicu_foldingに近いですが、こちらは対象をBasic Latinに限定したものです。
したがって「ー」の伸ばし棒や「゛゜」といった濁点はそのまま残ります。

設定例

"index" : {
    "analysis" : {
        "analyzer" : {
            "default" : {
                "tokenizer" : "standard",
                "filter" : ["standard", "asciifolding"]
            }
        }
    }
}

icu_transform

token_filterの1つです。ひらがなや中国語をローマ字に変換できたり、ロシア語を発音通りのアルファベットに変換できたりします。
設定はidによって様々で、組み合わせることもできます。詳細は以下です。

General Transforms - ICU User Guide

設定例

こちらはひらがなをカタカナに変換する設定です。

{
  "settings": {
    "index": {
      "analysis": {
        "analyzer": {
          "kana": {
            "tokenizer": "keyword",
            "filter": [
              "kana_filter"
            ]
          }
        },
        "filter": {
          "kana_filter": {
            "type": "icu_transform",
            "id": "Hiragana-Katakana" 
          }
        }
      }
    }
  }
}

ソース