Elasticsearch で Custom Analyzer 使ってみる!

Elasticsearch の Analyzer のカスタマイズ方法を調べてみようと思います。

Custom Analyzer を作る

基本はここに書いてありますね。

前回の記事でも載せましたが、Analyzer には3つの要素があり、カスタムで作る場合はそれらの要素を指定することになります。カスタムで作成した Analyzer は _analyze エンドポイントでも使用できますが、実際にはインデックスまたはクエリのときに使用します。

インデックスに Custom Analyzer を適用するにはこうします。

PUT my_index_2
{
  "settings": {
    "analysis": {
      "analyzer": { (1)
        "my_custom_analyzer": {
          "type": "custom", (2)
          "char_filter": [
            "emoticons"
          ],
          "tokenizer": "punctuation",
          "filter": [
           "lowercase",
           "english_stop"
          ]
        }
      },
      "tokenizer": {
        "punctuation": { (3)
          "type": "pattern",
          "pattern": "[ .,!?]"
        }
      },
      "char_filter": {
        "emoticons": { (4)
          "type": "mapping",
          "mappings": [
            ":) => _happy_",
            ":( => _sad_"
          ]
        }
      },
      "filter": { (5)
        "english_stop": {
          "type": "stop",
          "stopwords": "_english_"
        }
      }
    }
  }
}

(1) analyzer で独自の Analyzer を定義します。名前は my_custom_analyzer に指定しました。 (2) my_custom_analyzer Analyzer のタイプです。 custom または Built-in の Analyzer を指定します。このオブジェクトに使用する Analyzer の3つの要素を指定します。 (3) ~ (5) tokenizer char_filter filter を定義します。

Custom Analyzer の定義の仕方はわかりやすいですね。(3) ~ (5) では Built-in のものをカスタマイズして使っています。 tokenizer も独自のものをインストールすれば使えるのでしょうね。

ドキュメントには日本語の analysis-kuromoji プラグインのインストール方法が書いてありますね。

上で定義したインデックスの Analyzer を使うにはこう。

POST my_index_2/_analyze
{
  "analyzer": "my_custom_analyzer",
  "text": "I'm a :) person, and you?"
}
{
  "tokens" : [
    {
      "token" : "i'm",
      "start_offset" : 0,
      "end_offset" : 3,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "_happy_",
      "start_offset" : 6,
      "end_offset" : 8,
      "type" : "word",
      "position" : 2
    },
    {
      "token" : "person",
      "start_offset" : 9,
      "end_offset" : 15,
      "type" : "word",
      "position" : 3
    },
    {
      "token" : "you",
      "start_offset" : 21,
      "end_offset" : 24,
      "type" : "word",
      "position" : 5
    }
  ]
}

:)_happy_ に変換されました。

Custom でも、Built-int でも、インデックスのフィールドに Analyzer を指定するにはこうします。

PUT /my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "std_english": {
          "type": "standard",
          "stopwords": "_english_"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "my_text": {
        "type": "text",
        "analyzer": "standard", (1)
        "fields": {
          "english": {
            "type": "text",
            "analyzer": "std_english" (2)
          }
        }
      }
    }
  }
}

(1) Built-in の Analyzer を指定しました。 (2) Custom Analyzer を指定しました。

このようにすればドキュメントを保存するときに対象のフィールドがそれぞれテキスト解析されます。保存されるのはあくまでもドキュメント本体であり、解析されたテキストで置き換わるわけではないので注意です。

Analyzer を指定できる場所

以下のドキュメントに Analyzer を指定できる場所が書いてあります。

場所は以下の3つですね。

  • Index
  • text field
  • Query

text field への指定は既に載せた例の2つ目と同じです。

Index への指定は例の1つ目とほとんど同じです。違うのは Analyzer の名前を my_custom_analyzer から default に変更する点だけです。

Elasticsearch はドキュメントを保存するときに、テキストをどの Analyzer で解析するのかを、以下の順序で判断します。

  1. field に指定されている Analyzer
  2. analysis.analyzer.default に指定されている Analyzer
  3. standard analyzer

field と analysis.analyzer.default の両方に指定がある場合は field の Analyzer が優先されるわけですね。さらに、特に指定していなければ standard analyzer が使われます。

Query にも Analyzer を指定できるのですが、公式ドキュメン度でも謳っているように、基本は Index または field に指定されているものと同じ Analyzer を使うことをオススメしています。Query は field に Analyzer が設定されている場合はそれを使うのですが、 field の Analyzer がなく Index のみに Analyzer が指定されているだけの場合はその Analyzer を使ってくれないようです。この動きを見る限り、standard analyzer 以外を使うのであれば field ごとに Analyzer を明示指定したほうが良さそうですね。

公式ドキュメントには各 field に明示的に Analyzer を指定するシンプルな方法を取るべきだとも書いてあります。