

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

# チュートリアル: Amazon OpenSearch Service を用いて検索アプリケーションを作成する
<a name="search-example"></a>

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

この章では、Amazon API Gateway を使用して OpenSearch API APIsし、API Gateway から OpenSearch Service へのリクエストに署名 AWS Lambda するソリューションについて説明します。

![\[検索アプリケーションのフロー図。\]](http://docs.aws.amazon.com/ja_jp/opensearch-service/latest/developerguide/images/search-application-diagram.png)


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

## 前提条件
<a name="search-example-prereq"></a>

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

## ステップ 1: サンプルデータのインデックス作成
<a name="search-example-index"></a>

[sample-movies.zip](samples/sample-movies.zip) をダウンロードして解凍します。その後 [\$1bulk](https://opensearch.org/docs/latest/api-reference/document-apis/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: 複数のドキュメントをアップロードする](gsgupload-data.md#gsgmultiple-document)」を参照してください。

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

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

## ステップ 2: Lambda 関数を作成してデプロイする
<a name="search-example-lambda"></a>

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

### Lambda 関数を作成する
<a name="sample-lamdba-python"></a>

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

**デプロイパッケージを作成するには**

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

   ```
   mkdir my-opensearch-function
   ```

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

   ```
   cd my-opensearch-function
   ```

1. 次のサンプル 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
   ```

1. 新しい `package` ディレクトリに外部のライブラリをインストールします。

   ```
   pip3 install --target ./package boto3
   pip3 install --target ./package requests
   pip3 install --target ./package requests_aws4auth
   ```

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

   ```
   cd package
   zip -r ../my-deployment-package.zip .
   ```

1. zip ファイルのルートに `opensearch-lambda.py` ファイルを追加します。

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

Lambda 関数とデプロイパッケージの作成の詳細については、AWS Lambda デベロッパーガイドの「[.zip ファイルアーカイブで Python Lambda 関数をデプロイする](https://docs.aws.amazon.com/lambda/latest/dg/lambda-python-how-to-create-deployment-package.html)」と本ガイドの「[Lambda デプロイパッケージを作成する](integrations-s3-lambda.md#integrations-s3-lambda-deployment-package)」を参照してください。

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

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

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

1. 以下のフィールドを設定します。
   + 関数名: opensearch-function
   + ランタイム: Python 3.9
   + アーキテクチャ: x86\$164

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

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

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

## ステップ 3: API Gateway で API を作成する
<a name="search-example-api"></a>

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

### API の作成と設定
<a name="create-api"></a>

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

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

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

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

1. 以下のフィールドを設定します。
   + API 名: **opensearch-api**
   + 説明: **Amazon OpenSearch Service ドメイン検索用のパブリック API**
   + エンドポイントタイプ: **リージョン別**

1. **[API の作成]** を選択します。

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

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

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


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

### メソッドリクエストの設定
<a name="method-request"></a>

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


| 設定 | 値 | 
| --- | --- | 
| Authorization | なし | 
| リクエストの検証 |  クエリ文字列パラメータ、およびヘッダーの検証   | 
| API キーが必要です | false | 

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


| 設定 | 値 | 
| --- | --- | 
| 名前 | q | 
| 必須 |  はい  | 

### API のデプロイとステージの設定
<a name="deploy-api"></a>

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

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

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

1. **[デプロイ]** をクリックします。

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


| 設定 | 値 | 
| --- | --- | 
| スロットリングの有効化 | はい | 
| 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 の作成](https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-create-api.html)」および「[Amazon API Gateway での REST API のデプロイ](https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-deploy-api.html)」を参照してください。

## ステップ 4 (オプション): ドメインアクセスポリシーを変更する
<a name="search-example-perms"></a>

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

------
#### [ JSON ]

****  

```
{
  "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」を検索します。

------
#### [ JSON ]

****  

```
{
  "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 で[ロールをユーザーにマッピングする](fgac.md#fgac-mapping)必要もあります。マッピングを行わないと、アクセス許可エラーが表示されます。

### Lambda 実行ロールのアクセス許可の設定
<a name="search-example-lambda-iam"></a>

ドメインアクセスポリシーの設定に加えて、Lambda 実行ロールに OpenSearch Service ドメインにアクセスするために必要な IAM アクセス許可があることを確認する必要があります。Lambda 関数には、マネージドドメインと OpenSearch Service Serverless コレクションのどちらを使用しているかに応じて、特定のアクセス許可が必要です。

**マネージド OpenSearch Service ドメインの場合:**

以下の IAM ポリシーを Lambda 実行ロールにアタッチして、OpenSearch Service ドメインへのリクエストを許可します。

------
#### [ JSON ]

****  

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

------

**OpenSearch Service Serverless コレクションの場合:**

OpenSearch Service Serverless を使用している場合は、以下の IAM ポリシーを Lambda 実行ロールにアタッチします。

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "aoss:*",
      "Resource": "arn:aws:aoss:us-west-1:123456789012:collection/collection-id"
    }
  ]
}
```

------

Lambda 実行ロールにこれらのポリシーをアタッチするには:

1. IAM コンソール ([https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/)) に移動します。

1. **[ロール]** を選択し、Lambda 実行ロールを検索します (通常は `opensearch-lambda-role-xxxxxxxx` という名前です)。

1. **[アクセス許可の追加]** を選択し、次いで **[インラインポリシーを作成]** を選択します。

1. **[JSON]** タブを選択し、上記から適切なポリシーを貼り付けて、プレースホルダー値を実際のリソース ARN に置き換えます。

1. **[ポリシーの確認]** を選択し、`OpenSearchAccess` のような名前を入力して、**[ポリシーの作成]** を選択します。

**注記**  
上記の IAM アクセス許可がない場合、ドメインアクセスポリシーでリクエストが許可されている場合でも、Lambda 関数が OpenSearch Service ドメインにクエリしようとすると「アクセスが拒否されました」のエラーが発生します。

アクセスポリシーの詳細については、「[アクセスポリシーの設定](createupdatedomains.md#createdomain-configure-access-policies)」を参照してください。

## Lambda ロールをマッピングする (きめ細かなアクセスコントロールを使用している場合)
<a name="search-example-perms-fgac"></a>

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

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

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

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

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

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

## ステップ 5: ウェブアプリケーションをテストする
<a name="search-example-webpage"></a>

**ウェブアプリケーションをテストするには**

1. [sample-site.zip](samples/sample-site.zip) をダウンロードして解凍し、お気に入りのテキストエディタで `scripts/search.js` を開きます。

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

1. `index.html` を開き、*thor*、*house*、および他のいくつかの用語の検索を実行してみてください。  
![\[thor の検索例。\]](http://docs.aws.amazon.com/ja_jp/opensearch-service/latest/developerguide/images/search-ui.png)

### CORS エラーのトラブルシューティング
<a name="search-example-cors"></a>

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 を有効化](https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors-console.html)します。**[Advanced] ** (アドバンスト) の下で、**[Access-Control-Allow-Credentials]** を `'true'` にセットします。

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

1. Lambda 関数トリガーを削除して再追加します。[re-add] (再追加) を追加し、**[Add trigger]** (トリガーを追加) を選択して、関数を呼び出す HTTP エンドポイントを作成します。トリガーには、次の設定がある必要があります。    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/opensearch-service/latest/developerguide/search-example.html)

## 次の手順
<a name="search-example-next"></a>

この章は、概念を示すための出発点にすぎません。例えば、次のような変更が考えられます。
+ OpenSearch Service ドメインに独自のデータを追加します。
+ API にメソッドを追加します。
+ Lambda 関数では、検索クエリを変更するか、異なるフィールドを追加します。
+ 結果のスタイルを変更するか、`search.js` を変更してユーザーに異なるフィールドを表示します。