チュートリアル: Amazon OpenSearch Service を用いて検索アプリケーションを作成する - Amazon OpenSearch サービス

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

チュートリアル: Amazon OpenSearch Service を用いて検索アプリケーションを作成する

Amazon OpenSearch Service を用いて検索アプリケーションを作成する一般的な方法は、サーバーへのユーザークエリを送信するウェブフォームを使用することです。次に、OpenSearch API を直接呼び出すようサーバーを承認し、サーバーが OpenSearch Service にリクエストを送信するようにします。ただし、サーバーに依存しないクライアント側のコードを記述する場合は、セキュリティとパフォーマンスのリスクを補正する必要があります。OpenSearch API への、署名されていないパブリックアクセスを許可することはお勧めしません。ユーザーは、保護されていないエンドポイントにアクセスしたり、過度に広範なクエリ (または多すぎるクエリ) によりクラスターのパフォーマンスに影響を及ぼす可能性があります。

この章では、解決方法を提示します。Amazon API Gateway を使用してユーザーを OpenSearch API のサブセットに制限し、AWS Lambda を使用して API Gateway から OpenSearch Service へのリクエストに署名します。


            検索アプリケーションのフロー図。
注記

スタンダードの API Gateway および Lambda 料金表が適用されますが、このチュートリアル内での使用は限定されているため、費用はごくわずかです。

前提条件

このチュートリアルの前提条件は、OpenSearch Service ドメインです。まだドメインを持っていない場合は、「OpenSearch Service ドメインを作成する」のステップに従って、ドメインを作成します。

ステップ 1: サンプルデータのインデックス作成

sample-movies.zip をダウンロードして解凍します。その後 _bulk API オペレーションを使用して、movies インデックスに 5,000 個のドキュメントを追加します。

POST https://search-my-domain.us-west-1.es.amazonaws.com/_bulk { "index": { "_index": "movies", "_id": "tt1979320" } } {"directors":["Ron Howard"],"release_date":"2013-09-02T00:00:00Z","rating":8.3,"genres":["Action","Biography","Drama","Sport"],"image_url":"http://ia.media-imdb.com/images/M/MV5BMTQyMDE0MTY0OV5BMl5BanBnXkFtZTcwMjI2OTI0OQ@@._V1_SX400_.jpg","plot":"A re-creation of the merciless 1970s rivalry between Formula One rivals James Hunt and Niki Lauda.","title":"Rush","rank":2,"running_time_secs":7380,"actors":["Daniel Brühl","Chris Hemsworth","Olivia Wilde"],"year":2013,"id":"tt1979320","type":"add"} { "index": { "_index": "movies", "_id": "tt1951264" } } {"directors":["Francis Lawrence"],"release_date":"2013-11-11T00:00:00Z","genres":["Action","Adventure","Sci-Fi","Thriller"],"image_url":"http://ia.media-imdb.com/images/M/MV5BMTAyMjQ3OTAxMzNeQTJeQWpwZ15BbWU4MDU0NzA1MzAx._V1_SX400_.jpg","plot":"Katniss Everdeen and Peeta Mellark become targets of the Capitol after their victory in the 74th Hunger Games sparks a rebellion in the Districts of Panem.","title":"The Hunger Games: Catching Fire","rank":4,"running_time_secs":8760,"actors":["Jennifer Lawrence","Josh Hutcherson","Liam Hemsworth"],"year":2013,"id":"tt1951264","type":"add"} ...

上記は、利用可能なデータの、ごく一部のコマンド例であることにご注意ください。_bulk オペレーションを実行するには、sample-movies ファイルのコンテンツ全体をコピーして貼り付ける必要があります。詳細な手順については、「オプション 2: 複数のドキュメントをアップロードする」を参照してください。

次のように curl コマンドを使用しても同じ結果が得られます。

curl -XPOST -u 'master-user:master-user-password' 'domain-endpoint/_bulk' --data-binary @bulk_movies.json -H 'Content-Type: application/json'

ステップ 2: Lambda 関数を作成してデプロイする

API Gateway で API を作成する前に、リクエストを渡す Lambda 関数を作成します。

Lambda 関数を作成する

このソリューションでは、API Gateway は Lambda 関数にリクエストを渡します。この関数は OpenSearch Service にクエリを送り、結果を返します。このサンプル関数は外部ライブラリを使用するため、デプロイパッケージを作成して Lambda にアップロードする必要があります。

デプロイパッケージを作成するには
  1. コマンドプロンプトを開き、my-opensearch-function プロジェクトディレクトリを作成します。例えば、macOS では次のようになります。

    mkdir my-opensearch-function
  2. my-sourcecode-function プロジェクトディレクトリに移動します。

    cd my-opensearch-function
  3. 次のサンプル Python コードの内容をコピーし、opensearch-lambda.py という名前の新しいファイルに保存します。リージョンとホストエンドポイントをファイルに追加します。

    import boto3 import json import requests from requests_aws4auth import AWS4Auth region = '' # For example, us-west-1 service = 'es' credentials = boto3.Session().get_credentials() awsauth = AWS4Auth(credentials.access_key, credentials.secret_key, region, service, session_token=credentials.token) host = '' # The OpenSearch domain endpoint with https:// and without a trailing slash index = 'movies' url = host + '/' + index + '/_search' # Lambda execution starts here def lambda_handler(event, context): # Put the user query into the query DSL for more accurate search results. # Note that certain fields are boosted (^). query = { "size": 25, "query": { "multi_match": { "query": event['queryStringParameters']['q'], "fields": ["title^4", "plot^2", "actors", "directors"] } } } # Elasticsearch 6.x requires an explicit Content-Type header headers = { "Content-Type": "application/json" } # Make the signed HTTP request r = requests.get(url, auth=awsauth, headers=headers, data=json.dumps(query)) # Create the response and add some extra content to support CORS response = { "statusCode": 200, "headers": { "Access-Control-Allow-Origin": '*' }, "isBase64Encoded": False } # Add the search results to the response response['body'] = r.text return response
  4. 新しい package ディレクトリに外部のライブラリをインストールします。

    pip3 install --target ./package boto3 pip3 install --target ./package requests pip3 install --target ./package requests_aws4auth
  5. ルートにインストール済みライブラリを含むデプロイパッケージを作成します。次のコマンドを使ってプロジェクトディレクトリに my-deployment-package.zip ファイルを生成します。

    cd package zip -r ../my-deployment-package.zip .
  6. zip ファイルのルートに opensearch-lambda.py ファイルを追加します。

    cd .. zip my-deployment-package.zip opensearch-lambda.py

Lambda 関数とデプロイパッケージの作成の詳細については、AWS Lambda デベロッパーガイドの「.zip ファイルアーカイブで Python Lambda 関数をデプロイする」と本ガイドの「Lambda デプロイパッケージを作成する」を参照してください。

Lambda コンソールを使って関数を作成するには

  1. Lambda コンソール (https://console.aws.amazon.com/lambda/home) に進みます。ナビゲーションペインで、[Functions] (関数) を選択します。

  2. [Create Function] (関数を作成) を選択します。

  3. 次のフィールドを設定します。

    • 関数名: opensearch-function

    • ランタイム: Python 3.9

    • アーキテクチャ: x86_64

    他のオプションはすべてデフォルトのままにして、[Create function] を選択します。

  4. 関数の概要ページの[Code source] (コードソース) セクションで、ドロップダウンから [Upload from] (アップロード元) を選択し、[.zip file] (.zip ファイル) を選択します。my-deployment-package.zip 作成したファイルを見つけて、[Save] (保存) を選択します。

  5. ハンドラーとは、イベントを処理する関数コード内のメソッドです。[Runtime settings] (ランタイム設定) の下で [Edit] (編集) を選択し、Lambda 関数が配置されているデプロイパッケージ内の、ファイルの名前に従ってハンドラー名を変更します。例えば、ファイルの名前が opensearch-lambda.py の場合、ハンドラー名を opensearch-lambda.lambda_handler に変更します。詳細については、「Python の Lambda 関数ハンドラー」を参照してください。

ステップ 3: API Gateway で API を作成する

API Gateway を使用してさらに制限された API を作成することで、OpenSearch _search API とのやり取りのプロセスを簡素化することができます。API Gateway により、Amazon Cognito 認証やリクエストスロットリングなどのセキュリティ機能を有効にすることもできます。API を作成してデプロイするには、以下のステップを実施します。

API の作成と設定

API Gateway コンソールを使用して API を作成するには

  1. API Gateway コンソール (https://console.aws.amazon.com/apigateway/home) に移動します。ナビゲーションペインで、[API] を選択します。

  2. [REST API] (プライベートではない) を見つけ、[構築] を選択します。

  3. 次のページの [Create new API] (新しい API を作成) セクションで、[New API] (新規 API) が選択されていることを確認します。

  4. 次のフィールドを設定します。

    • API 名: opensearch-api

    • 説明: Amazon OpenSearch Service ドメイン検索用のパブリック API

    • エンドポイントタイプ: リージョン別

  5. API の作成 を選択します。

  6. [アクション] および [メソッドの作成] を選択します。

  7. ドロップダウンで [GET] を選択し、チェックマークをクリックして確定します。

  8. 以下の設定を行い、[保存] を選択します。

設定 Value
統合タイプ Lambda 関数
Lambda プロキシ統合の使用 はい
Lambda のリージョン us-west-1
Lambda 関数 opensearch-lambda
デフォルトタイムアウトの使用 はい

メソッドリクエストの設定

[メソッドリクエスト] を選択して、以下の設定を行います。

設定 Value
認証 なし
リクエストの検証

クエリ文字列パラメータ、およびヘッダーの検証

API キーが必要です false

[URL Query String Parameters] (URL クエリ文字列パラメータ) の下で [Add query string] (クエリ文字列を追加) を選択し、次のパラメータを設定します。

設定 Value
名前 q
必須

はい

API のデプロイとステージの設定

API Gateway コンソールでは、デプロイを作成して新規または既存のステージに関連付けることで API をデプロイできます。

  1. [アクション] および [API のデプロイ] を選択します。

  2. [デプロイステージ] では、[新しいステージ] を選択し、ステージ opensearch-api-test に名前を付けます。

  3. [Deploy‬] (デプロイ) をクリックします。

  4. ステージエディタで以下の設定を行い、[変更の保存] を選択します。

設定 Value
スロットリングの有効化 はい
Rate

1,000

バースト 500

これらの設定は、エンドポイントのルート (https://some-id.execute-api.us-west-1.amazonaws.com/search-es-api-test) への ​GET リクエストという 1 つのメソッドのみを持つ API を設定します。リクエストに必要なのは、検索するクエリ文字列という 1 つのパラメータ (q) です。呼び出されると、メソッドは opensearch-lambda 関数を実行する Lambda にリクエストを渡します。詳細については、「Amazon API Gateway での API の作成」および「Amazon API Gateway での REST API のデプロイ」を参照してください。

ステップ 4 (オプション): ドメインアクセスポリシーを変更する

OpenSearch Service ドメインで、Lambda 関数が movies インデックスへの GET リクエストを行うことを許可する必要があります。きめ細かなアクセスコントロールが有効になっているドメインで未処理のアクセスポリシーがある場合は、そのまま使用できます。

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": "es:*", "Resource": "arn:aws:es:us-west-1:123456789012:domain/domain-name/*" } ] }

または、所持しているドメインアクセスポリシーをよりきめ細かにすることもできます。例えば、次の最小限のポリシーは、movies インデックスへの opensearch-lambda-role (Lambda を通じて作成された) 読み取りアクセスを提供します。Lambda が自動的に作成するロールの正確な名前を取得するには、AWS Identity and Access Management (IAM) コンソールに進み、ロールを選択し、「lambda」を検索します。

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::123456789012:role/service-role/opensearch-lambda-role-1abcdefg" }, "Action": "es:ESHttpGet", "Resource": "arn:aws:es:us-west-1:123456789012:domain/domain-name/movies/_search" } ] }
重要

きめ細かなアクセスコントロールがドメインに対して有効になっている場合は、OpenSearch Dashboards でロールをユーザーにマッピングする必要もあります。マッピングを行わないと、アクセス許可エラーが表示されます。

アクセスポリシーの詳細については、「アクセスポリシーの設定」を参照してください。

Lambda ロールをマッピングする (きめ細かなアクセスコントロールを使用している場合)

きめ細かなアクセスコントロールでは、アプリケーションをテストする前に追加のステップが導入されます。HTTP 基本認証を他のすべての目的で使用する場合でも、ユーザーに Lambda ロールをマッピングする必要があります。マッピングを行わないと、アクセス許可エラーが表示されます。

  1. ドメインの OpenSearch Dashboards URL に移動します。

  2. メインメニューから [Security] (セキュリティ)、[Roles] (ロール) の順に選択し、Lambda ロールをマッピングするロールである all_access へのリンクを選択します。

  3. [マッピングされたユーザー]、[マッピングの管理] を選択します。

  4. [Backend roles] (バックエンドロール) で、Lambda ロールの Amazon リソースネーム (ARN) を追加します。ARN は arn:aws:iam::123456789123:role/service-role/opensearch-lambda-role-1abcdefg の形式にします。

  5. [マップ] を選択し、ユーザーまたはロールが [マッピングされたユーザー] の下に表示されていることを確認します。

ステップ 5: ウェブアプリケーションをテストする

ウェブアプリケーションをテストするには
  1. sample-site.zip をダウンロードして解凍し、お気に入りのテキストエディタで scripts/search.js を開きます。

  2. API Gateway エンドポイントを指すように apigatewayendpoint 変数を更新し、所定のパスの最後にバックスラッシュを追加します。[Stages] (ステージ) と API の名前を選択することで、API ゲートウェイでエンドポイントをすばやく見つけることができます。apigatewayendpoint 変数は https://some-id.execute-api.us-west-1.amazonaws.com/opensearch-api-test/ の形式にします。

  3. index.html を開き、thorhouse、および他のいくつかの用語の検索を実行してみてください。

    
                        thor の検索例。

CORS エラーのトラブルシューティング

Lambda 関数で CORS をサポートするための応答にコンテンツが含まれていても、次のエラーが表示される場合があります。

Access to XMLHttpRequest at '<api-gateway-endpoint>' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present in the requested resource.

このような場合は、以下のことを試してみます。

  1. GET リソースで CORS を有効化します。[Advanced] (アドバンスト) の下で、[Access-Control-Allow-Credentials]'true' にセットします。

  2. API ゲートウェイ ([Actions] (アクション)、[Deploy API] (API のデプロイ)) で API を再デプロイします。

  3. Lambda 関数トリガーを削除して再追加します。[re-add] (再追加) を追加し、[Add trigger] (トリガーを追加) を選択して、関数を呼び出す HTTP エンドポイントを作成します。トリガーには、次の設定がある必要があります。

    トリガー API デプロイされるステージ セキュリティ
    API Gateway opensearch-api opensearch-api-test 開く

次のステップ

この章は、概念を示すための出発点にすぎません。例えば、次のような変更が考えられます。

  • OpenSearch Service ドメインに独自のデータを追加します。

  • API にメソッドを追加します。

  • Lambda 関数では、検索クエリを変更するか、異なるフィールドを追加します。

  • 結果のスタイルを変更するか、search.js を変更してユーザーに異なるフィールドを表示します。