Amazon Web Services ブログ

Amazon OpenSearch Serviceにおけるカスタムパッケージと辞書ファイルのホットリロード

この記事は、Custom packages and hot reload of dictionary files with Amazon OpenSearch Service を翻訳したものです。

Amazon OpenSearch Service は、AWS クラウド上に OpenSearch クラスターをコスト効率よく大規模にデプロイ・運用するために利用できるフルマネージドサービスです。本サービスでは、最新バージョンの OpenSearch、19 個のバージョンのElasticsearch (バージョン 1.5~7.10) のサポート、OpenSearch Dashboards と Kibana (バージョン 1.5~7.10) による可視化機能により、インタラクティブなログ分析、リアルタイムアプリケーション監視、ウェブサイト検索などを容易に実行することが可能になります。

ウェブサイト検索、EC サイト検索、エンタープライズサーチなど、ユーザーが特定の語句に対して関連性のあるコンテンツを取得したい場合、さまざまなユースケースがあります。検索エンジンは、クエリAPI を通じて送られてきた用語 (単語) を照合します。同じ概念を表す表現が多くある場合、シノニムを使用して、ユーザーが入力したものよりも多くのマッチ対象を検索エンジンに与えることができます。

同様に、入力データに一般的な単語や頻出単語が多く、検索クエリで使用してもあまり関連性が高まらないようなユースケースもあります。例えば、”the”、”this”、”that “などの単語がこれにあたります。これらはストップワードとして分類できます。

OpenSearch Serviceでは、カスタム辞書ファイルをアップロードすることができ、シノニムやストップワードも含めて、ユースケースに合わせてカスタマイズすることが可能です。これは、特に以下のようなユースケースに有効です。

  • 等価に扱える単語を指定するケース。例えば、”bread“, ”danish“, ”croissant“ などの単語をシノニムとして扱うように指定することができます。これにより、完全一致しない場合に NULL を返す代わりに、関連性があると考えられる、または同等の結果が返されるため、より良い検索結果が得られるようになります。
  • 一般的で、検索の関連性スコアに貢献するという点で有益な情報を持たない、特定の高頻度語を無視するケース。これには、“a”, “the”, “of”, “an” などが含まれる可能性があります。

シノニム、ストップワードを指定すると、クエリの精度が大幅に向上し、クエリの関連性をカスタマイズして向上させることができます。また、ステミングにも役立ちます (日本語 の kuromoji 分析プラグインなど)。ステミングとは、単語をその語源に還元することです。たとえば、”cooking” と “cooked” は、同じ語根の “cook” にステム処理されることがあります。このように、ある単語のあらゆるバリエーションを1つの語源にステミングすることで、クエリ結果を向上させることができます。

この記事では、OpenSearch Service のドメインにシノニムとストップワード用のカスタムパッケージを追加する方法を紹介します。まず、シノニムとストップワード用のカスタムパッケージを作成し、標準トークナイザーとシノニムトークンフィルターを使用するサンプルインデックス用のカスタムアナライザーを作成し、その後、辞書ファイルのホットリロードのデモンストレーションを実施します。

トークナイザーとトークンフィルター

トークナイザーは、ある規則に基づいて文字のストリームをトークン (通常は単語) に分割します。最も単純な例は、Whitespace Tokenizer で、空白文字に遭遇するたびに直前の文字をトークンに分解します。より複雑な例としては、Standard Tokenizer があります。これは、文法に基づく規則のセットを使用して、多くの言語にわたって機能します。

トークンフィルターは、トークンを追加、修正、削除します。たとえば、シノニムトークンフィルターは、シノニムリストで単語を見つけるとトークンを追加します。ストップトークンフィルターは、ストップワードリストにある単語を見つけるとトークンを削除します。

前提条件

本デモの実行にあたり、実行中(稼働中 or 動作中)の OpenSearch Service クラスター(バージョン 1.2) が必要です。この機能は、7.8 以上のバージョンが動作している OpenSearch Serviceでも使用することができます。

管理者権限を持たないユーザーがパッケージを管理するには、es:CreatePackage, es:DeletePackage, es:AssociatePackage, es:DissociatePackageAWS Identity and Access Management (IAM) アクションが必要です。また、カスタムパッケージが存在するAmazon Simple Storage Service (Amazon S3) のバケットパスまたはオブジェクトに対する権限も必要です。ドメインアクセスポリシーではなく、 IAM 内ですべての権限を付与します。これにより、パーミッションの変更はドメインとは別に行うことができるため、パーミッションの管理が容易になり、ユーザーは (必要に応じて) 複数の OpenSearch Serviceドメインで同じアクションを実行できるようになります。

カスタムパッケージのセットアップ

ソリューションをセットアップするには、次の手順を実行します。

  1. Amazon S3 コンソールで、カスタムパッケージを格納するためのバケットを作成します。
  2. このバケットに、ストップワードとシノニムを含むファイルをアップロードします。今回の投稿では、ファイルの中身は以下の通りです。
    1. synonyms.txt:
      pasta, penne, ravioli 
      ice cream, gelato, frozen custard
      danish, croissant, pastry, bread
    2. stopwords.txt:
      the
      a
      an
      of

以下のスクリーンショットは、アップロードされたファイルを示しています。

次に、パッケージをインポートして、ドメインと関連付けます。

  1. OpenSearch Service コンソールで、ナビゲーションペインから Packages を選択します。
  1. Import Package を選択します。
  1. パッケージの名前 (シノニムパッケージの場合、my-custom-synonym-package を使用) とオプションの説明を入力してください。
  2. Package source には、synonyms.txt が格納されている S3 の場所を入力します。
  3. Submit を選択します。
  1. 以下の手順を繰り返して、stopwords.txt を含むパッケージを作成します。
  2. シノニムパッケージのステータスが Available と表示されている場合は、シノニムパッケージを選択します。
  1. Associate to domain を選択します。
  1. OpenSearch Serviceのドメインを選択し、Associate を選択します。
  1. この手順を繰り返して、OpenSearch Service のドメインを stopwords パッケージと関連付けます。
  2. パッケージが利用できるようになったら、その ID をメモしておきます。

OpenSearch へのリクエストでは、ファイルパスとして analyzers/id を使用します。

自前のデータでのカスタムパッケージの使用

ファイルをドメインに関連付けた後、トークナイザーやトークンフィルタを作成する際に synonyms_pathstopwords_path などのパラメータで使用することができます。詳しくは、OpenSearch Service をご覧ください。

OpenSearch Service ドメインで以下のスニペットを使用して新しいインデックス (my-index-test) を作成し、 synonyms パッケージと stopwords パッケージに Analyzers/id の値を指定できます。

  1. OpenSearch Dashboards を開きます。
  2. Home メニューから Dev Tools を選択します。
  1. 左ペインに以下のコードを入力します。
  2. 
    PUT my-index-test
    {
      "settings": {
        "index": {
          "analysis": {
            "analyzer": {
              "my_analyzer": {
                "type": "custom",
                "tokenizer": "standard",
                "filter": ["my_stop_filter" , "my_synonym_filter"]
              }
            },
            "filter": {
              "my_stop_filter": {
                "type": "stop",
                "stopwords_path": "analyzers/Fxxxxxxxxx",
                "updateable": true
              },
              "my_synonym_filter": {
                "type": "synonym",
                "synonyms_path": "analyzers/Fxxxxxxxxx",
                "updateable": true
              }
                
            }
          }
        }
      },
      "mappings": {
        "properties": {
          "description": {
            "type": "text",
            "analyzer": "standard",
            "search_analyzer": "my_analyzer"
          }
        }
      }
    }
  1. 再生ボタンを押すと、シノニムとストップワードでインデックスを作成するためのリクエストが送信されます。

次の画面は、リクエストの結果を示したものです。

このリクエストは、標準のトークナイザーとシノニムとストップトークンフィルターを使用する、ユーザー毎のインデックス用のカスタムアナライザーを作成します。このリクエストはまた、マッピングにテキストフィールド (description) を追加し、 OpenSearch に新しいアナライザーをサーチアナライザーとして使用するよう指示します。インデックスアナライザーとしては、これまでどおり標準のアナライザーを使用します。

トークンフィルターにある "updateable": true という行に注目しましょう。このフィールドは サーチアナライザーにのみ適用され、インデックスアナライザーには適用されません。後でサーチアナライザーを自動的に更新したい 場合は、このフィールドが必須となります。

まず、いくつかのサンプルデータを my-index-test インデックスに追加してみましょう。

POST _bulk
{ "index": { "_index": "my-index-test", "_id": "1" } }
{ "description": "pasta" }
{ "index": { "_index": "my-index-test", "_id": "2" } }
{ "description": "the bread" }
{ "index": { "_index": "my-index-test", "_id": "3" } }
{ "description": "ice cream" }
{ "index": { "_index": "my-index-test", "_id": "4" } }
{ "description": "croissant" }


これで、synonyms.txt ファイルで指定した単語を検索すると、必要な結果が得られます。なお、私のテストインデックスでは、インデックスされたデータには pasta しかありませんが、関連パッケージで pasta のシノニムとして ravioli を指定したので、 ravioli を検索すると、 pasta という単語を持つすべてのドキュメントの結果が得られます。

GET my-index-test/_search
{
  "query": {
    "match": {
      "description": "ravioli"
    }
  }
}


同様に、検索結果を表示するときに除外でき、検索クエリの結果返却時に関連性にあまり影響を与えない一般的な単語をストップワード機能を使って指定できます。

ホットリロード

ここで、“pasta” のシノニム (“spaghetti”) をもう一つ追加しましょう。

  1. まず、synonyms.txt ファイルを以下のように更新し、この更新したファイルを S3 バケットにアップロードします。
  2. pasta , penne , ravioli, spaghetti
    ice cream, gelato, frozen custard
    danish, croissant, pastry , bread

Amazon S3 にパッケージの新バージョンをアップロードしても、OpenSearch Service 上のパッケージは自動的に更新されません。OpenSearch Service はファイルのコピーを独自に保存するので、Amazon S3 に新しいバージョンをアップロードした場合は、OpenSearch Service で手動で更新する必要があります。

この時点で “spaghetti” という用語のインデックスに対する検索クエリを実行しようとしても、結果は得られません。

GET my-index-test/_search
{
  "query": {
    "match": {
      "description": "spaghetti"
    }
  }
}


Amazon S3 でファイルを変更した後、OpenSearch Service でパッケージを更新し、更新を適用します。これを行うには、以下の手順を実行します。

  1. OpenSearch Service コンソールで、Packages を選択します。
  2. カスタムシノニム用に作成したパッケージを選択し、Update を選択します。
  1. ファイルのS3パスを指定し、Update package を選択します。
  1. 説明を入力し、Update package を選択します。

Package のページに戻ります。

  1. パッケージのステータスが Available と表示されたら、それを選択し、関連するドメインが更新されたと表示されるのを待ちます。
  2. ドメインを選択し、Apply update を選択します。
  1. もう一度、Apply update を選択して確定します。

Association のステータスが Active に変わるのを待って、パッケージのバージョンも更新されたことを確認します。

Elasticsearch 7.7 以前のドメインで、インデックスアナライザーを使用している場合、または updatable フィールドを使用していない場合で、後からいくつかのシノニムを追加したい場合、新しい辞書ファイルでデータを再インデックスする必要があります。以前は、Amazon Elasticsearch Service 上では、これらのアナライザーは、インデックスされたデータしか処理できませんでした。

お客様のドメインで OpenSearch Service または Amazon Elasticsearch Service 7.8 以降が動作し、updateable フィールドを true に設定したサーチアナライザのみを使用する場合、これ以上の対処は必要ありません。OpenSearch Service は、_plugins/_refresh_search_analyzers API を使用してインデックスを自動的に更新します。これにより、インデックスを close して open し直すことなく、リアルタイムでサーチアナライザを更新することができます。

ホットリロードと呼ばれるこの機能は、データを再インデックスすることなく、辞書ファイルを再読み込みする機能を提供します。この新しいホットリロード機能により、検索時にアナライザーを呼び出し、辞書ファイルによってクエリーを補強することができます。また、この機能により、データを再インデックス化することなく、OpenSearch Service で辞書ファイルをバージョン管理し、ドメイン上で更新することができます。

このデモで使用したドメインは OpenSearch Service 1.2 なので、このホットリロード機能を利用すれば、データの再インデックスを行うことなく、この機能を利用することができます。新しく追加されたシノニム (“spaghetti”) の検索クエリを実行するだけで、そのシノニムを含むすべての結果文書が得られます。

GET my-index-test/_search
{
  "query": {
    "match": {
      "description": "spaghetti"
    }
  }
}

結論

この投稿では、OpenSearch Service にシノニムを簡単に設定する方法を紹介し、特定の単語が検索語として使用されていない場合でも、その単語のシノニムに一致する関連文書を見つけることができるようにしました。また、既存のシノニム辞書を追加・更新し、それらのファイルを読み込んで変更を反映させる方法についても紹介しました。

この記事に関するフィードバックがありましたら、コメント欄にご記入ください。また、OpenSearch Service フォーラム で新しいスレッドを立ち上げるか、AWSサポート に質問してください。

翻訳は Solutions Architect 深見が担当しました。

TAGS: Amazon OpenSearch Service, Analytics