AWS CloudSearch で映画データの全文検索を行う
公開されている映画データセットを AWS CloudSearch にインデックスし、全文検索・数値検索・範囲検索を実行します。
AWS CloudSearch を使えば、別途検索クラスターを構築せずに、映画データセットをインデックスして全文検索できます。
CloudSearch ドメインのセットアップ
CloudSearch ドメインを作成します。
aws cloudsearch create-domain \ --domain-name searching-movies-data公式ドキュメントによると、CloudSearch ドメインの作成には通常およそ 10 分かかります。
ドメインの作成状況は以下のコマンドで確認できます。
aws cloudsearch describe-domains \ --domain-name searching-movies-dataコマンドの出力に Processing: false と表示されれば、ドメインとエンドポイントを利用できます。
{ "DomainStatusList": [ { "DomainId": "123456789012/searching-movies-data", "DomainName": "searching-movies-data", "ARN": "arn:aws:cloudsearch:ap-northeast-1:123456789012:domain/searching-movies-data", "Created": true, "Deleted": false, "DocService": { "Endpoint": "doc-searching-movies-data-xxxxxxxxxx.ap-northeast-1.cloudsearch.amazonaws.com" }, "SearchService": { "Endpoint": "search-searching-movies-data-xxxxxxxxxx.ap-northeast-1.cloudsearch.amazonaws.com" }, "RequiresIndexDocuments": false, "Processing": false, "SearchInstanceType": "search.small", "SearchPartitionCount": 1, "SearchInstanceCount": 1, "Limits": { "MaximumReplicationCount": 5, "MaximumPartitionCount": 10 } } ]}自分の IP アドレスからのみアクセスを許可するよう、ドメインのアクセスポリシーを更新します。
aws cloudsearch update-service-access-policies \ --domain-name searching-movies-data \ --access-policies ' { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "*", "Action": ["cloudsearch:*"], "Condition": {"IpAddress": {"aws:SourceIp": "xxx.xxx.xxx.xxx/32"}} } ] }'インデックスフィールドの設定
データセットの構造に合わせてインデックスフィールドを定義します。この例では、Kaggle の The Movies Dataset(CC0:Public Domain)を使用します。以下は、インデックスフィールドを定義するコマンドの例です。
aws cloudsearch define-index-field \ --domain-name searching-movies-data --name adult --type textaws cloudsearch define-index-field \ --domain-name searching-movies-data --name belongs_to_collection --type textaws cloudsearch define-index-field \ --domain-name searching-movies-data --name budget --type doubleaws cloudsearch define-index-field \ --domain-name searching-movies-data --name genres --type textaws cloudsearch define-index-field \ --domain-name searching-movies-data --name homepage --type textaws cloudsearch define-index-field \ --domain-name searching-movies-data --name id --type intaws cloudsearch define-index-field \ --domain-name searching-movies-data --name imdb_id --type textaws cloudsearch define-index-field \ --domain-name searching-movies-data --name original_language --type textaws cloudsearch define-index-field \ --domain-name searching-movies-data --name original_title --type textaws cloudsearch define-index-field \ --domain-name searching-movies-data --name overview --type textaws cloudsearch define-index-field \ --domain-name searching-movies-data --name popularity --type doubleaws cloudsearch define-index-field \ --domain-name searching-movies-data --name poster_path --type textaws cloudsearch define-index-field \ --domain-name searching-movies-data --name production_companies --type textaws cloudsearch define-index-field \ --domain-name searching-movies-data --name production_countries --type textaws cloudsearch define-index-field \ --domain-name searching-movies-data --name release_date --type textaws cloudsearch define-index-field \ --domain-name searching-movies-data --name revenue --type intaws cloudsearch define-index-field \ --domain-name searching-movies-data --name runtime --type doubleaws cloudsearch define-index-field \ --domain-name searching-movies-data --name spoken_languages --type textaws cloudsearch define-index-field \ --domain-name searching-movies-data --name status --type textaws cloudsearch define-index-field \ --domain-name searching-movies-data --name tagline --type textaws cloudsearch define-index-field \ --domain-name searching-movies-data --name title --type textaws cloudsearch define-index-field \ --domain-name searching-movies-data --name video --type textaws cloudsearch define-index-field \ --domain-name searching-movies-data --name vote_average --type doubleaws cloudsearch define-index-field \ --domain-name searching-movies-data --name vote_count --type int設定が完了したら、検索ドメインにドキュメントのインデックス作成を開始するよう指示します。
aws cloudsearch index-documents \ --domain-name searching-movies-dataデータセットのインデックス作成
Kaggle からデータセットをダウンロードし、先頭 1,000 行からなるサンプルファイルを用意します。
head -1000 movies_metadata.csv > sample.csvCloudSearch はコンソールから CSV ファイルを直接インデックスできますが、AWS CLI の aws cloudsearchdomain upload-documents コマンドは JSON または XML 形式のみを受け付けます。
Actions > Upload documents を選択します。

CSV ファイルを選択し、Next をクリックします。

検出されたフィールドを確認し、Upload documents をクリックします。


処理が完了したら、ヘッダーを除く 998 件のレコードがインデックスされたことを確認します。

クエリの実行
テキスト検索
title フィールドと overview フィールドを対象に、キーワード house で映画を検索します。
curl --location \ -g \ --request GET \ 'https://search-searching-movies-data-xxxxxxxxxx.ap-northeast-1.cloudsearch.amazonaws.com/2013-01-01/search?q=house&q.options={fields:["title","overview"]}&return=title,overview' | jq .レスポンスには、以下のようなマッチした結果が含まれます。
{ "status": { "rid": "8fDJv8swsgEK1DyD", "time-ms": 1 }, "hits": { "found": 26, "start": 0, "hit": [ { "id": "local_file_466", "fields": { "overview": "Hip Hop duo Kid & Play return...", "title": "House Party 3" } }, ... ] }}詳細については公式ドキュメントを参照してください。
数値検索
数値検索の例として、vote_average が 5.0 の映画を検索します。
curl --location --request GET 'https://search-searching-movies-data-xxxxxxxxxx.ap-northeast-1.cloudsearch.amazonaws.com/2013-01-01/search?q.parser=structured&q=vote_average:5.0&return=title,overview' | jq .レスポンスには、以下のようなマッチした結果が含まれます。
{ "status": { "rid": "w+Xgv8swwQEK1DyD", "time-ms": 0 }, "hits": { "found": 35, "start": 0, "hit": [ { "id": "local_file_144", "fields": { "overview": "Far from home...", "title": "The Amazing Panda Adventure" } }, ... ] }}詳細については公式ドキュメントを参照してください。
範囲検索
vote_average が 7.0 以上の映画を検索します。
curl --location \ -g \ --request GET \ 'https://search-searching-movies-data-xxxxxxxxxx.ap-northeast-1.cloudsearch.amazonaws.com/2013-01-01/search?q.parser=structured&q=vote_average:[7.0,}&return=title,overview' | jq .レスポンスには、以下のようなマッチした結果が含まれます。
{ "status": { "rid": "vJ/vv8swyAEK1DyD", "time-ms": 2 }, "hits": { "found": 254, "start": 0, "hit": [ { "id": "local_file_1", "fields": { "overview": "Led by Woody, Andy's toys...", "title": "Toy Story" } }, ... ] }}詳細については公式ドキュメントを参照してください。
クリーンアップ
作業が終わったらドメインを削除します。
aws cloudsearch delete-domain \ --domain-name searching-movies-dataまとめ
AWS CloudSearch では、別途検索クラスターを管理せずに、同じドメインで全文検索と数値検索を実行できます。q=house と、構造化クエリ q.parser=structured&q=vote_average:[7.0,} を使い分けることで、インデックスを追加設定せずに全文検索と数値範囲検索の両方に対応できます。
CloudSearch のエンドポイントはデフォルトでパブリックインターネットからアクセスできるため、ドメインの作成直後に update-service-access-policies を使い、アクセスポリシーを特定の aws:SourceIp に制限してください。
一連のセットアップを自動化する場合は、ドメインの作成に約 10 分かかることも考慮します。
Related posts
Cognito User Pools と OIDC で Slack サインインを実装する
Cognito user pool を OIDC 経由で Slack と連携させ、"Sign in with Slack" を Amplify で Next.js アプリケーションに組み込みます。
Lambda Web Adapter で FastAPI を AWS Lambda にデプロイする
FastAPI で書いた API バックエンドをコンテナ化し、Lambda Web Adapter と AWS CDK を使って単一の Lambda 関数へデプロイします。
API Gateway WebSocket:モック統合の実装
バックエンドの Lambda を使わず、モック統合のみで API Gateway WebSocket API を構築し、あらかじめ用意したレスポンスを返します。
CloudFront 署名付き URL 経由で S3 にアップロードする
CloudFront の署名付き URL を使い、独自ドメイン経由で S3 にアップロードする方法を紹介します。S3 の署名付き URL を直接使えない場合に有用です。
AWS EventBridge Scheduler:スケジュールに沿って EC2 を起動・停止する
Lambda を介さず、EventBridge Scheduler から EC2 API を直接呼び出し、cron スケジュールに従って EC2 インスタンスを起動・停止します。
