🐼

OpenSearch Analyzerで英語検索対応

に公開

OpenSearch Analyzerについて知ったので、メモしておきます。

はじめての OpenSearchは、こちら!

Analyzerとは

インデックス作成/検索時に、どのように文字列を解釈するのかをAnalyzerを指定することができます。

例えば、以下のように文字列を扱うことができます。
パンダより恋が苦手な私たち -> パンダ,,苦手,私たち
このように解析することによって、パンダより恋が苦手な私たちという作品名全文でなく、パンダというキーワードで検索ヒットするようになります。

Analyzer 何してる??

AWSの資料がわかりやすかったです。

  1. Character Filter
    • トークンに分割する前の、文字列の加工・置換処理
    • Character filters
      • mapping
        • 🐼 -> Panda
      • HTML strip
        • <p>Panda Book</p> -> Panda Book
  2. Tokenizer
    • 文字列から検索キーワードとしてヒットさせるための、トークンという単語単位に分割する処理
    • Tokenizers
      • The Ultimate Panda Book for Kids -> The,Ultimate,Panda,Book,for,Kids
        • デフォルトのStandard Tokenizerだと単純にスペースで単語が区切られる
        • 日本語の場合、スペースがないので、別途指定が必要そう。
  3. Token Filter
    • トークンの最終フィルタリング。検索に不要なものは省いたり、検索に最適化するために単数形にしたりする
    • Token Filters
      • stop(意味のないトークンを除外)
        • The,Ultimate,Panda,Book,for,Kids -> Ultimate,Panda,Book,Kids
      • stemmer(単語を語幹に変換)
        • Ultimateultim
        • Kids -> kid

英語対応した話

今回は海外向けサービスの検索機能実装だったため、英語で自然に検索できることが必要でした。
もともとデフォルトのStandard Tokenizerを利用していたのですが、、以下の場合にうまく検索できませんでした。

Panda's Sweet Life(仮名)というタイトルの作品があったが、Pnadaだけで検索してもヒットしない。スペースで区切られてトークン化されていることが原因で、Panda'sまで含めて検索しないとヒットしないようになっていた。

そのため、英語の意味を解釈して、トークン化するEnglish Analyzerを利用するよう対応しました。こちらを利用しておけば万事問題なさそうでした。
以下、実装ポイントを軽く記載しておきます。

インデックス作成

  • Index analyzers

  • 文字列のプロパティの場合にAnalyzerを設定する

  • 実装

    こんな感じ.rb
    index_body = {
      settings: {
        analysis: {
          analyzer: {
            default: {
              type: "english"
            }
          }
        }
      },
      mappings: {
        properties: {
          "id" => {
            type: "integer"
          },
          "name" => {
            type: "text",
            analyzer: "english"   # -> textの場合は指定!
          },
          "romaji_name" => {
            type: "text",
            analyzer: "english"
          },
        }
      }
    }
    @open_search_client.create_index(
      index_name: "anime_title_index",
      body: index_body,
    )
    

検索

  • Search analyzers

  • 実装

    こんな感じ.rb
    query = {
        size: 30,
        query: {
          multi_match: {
            query: @word,
            fields: [ "name^2", "romaji_name" ],
            analyzer: "english"  # -> ここで指定!
          }
        }
      }
    @open_search_client.search(
        index_name: "anime_title_index",
        query: query,
      )
    
    
  • インデックス作成時のマッピング設定でデフォルト値を設定できたっぽい、、

ちなみに日本語の場合

  • KuromojiというAnalyzerが使われがちっぽい
  • SudachiというAnalyzerもあり、Kuromojiよりも精度/カスタマイズ性が高いらしい

まとめ

  • ぱんだだ

Discussion