AWS CloudSearchで映画データの全文検索を行う

AWS CloudSearchで映画データの全文検索を行う

公開されている映画データセットをAWS CloudSearchにインデックスし、全文検索・数値検索・範囲検索を実行します。

Takahiro Iwasa
7 min read

AWS CloudSearchを使えば、別途検索クラスタを構築しなくても、映画データセットをインデックスして全文検索を行うことができます。

CloudSearchドメインのセットアップ

CloudSearchドメインを作成します。

Terminal window
aws cloudsearch create-domain \
--domain-name searching-movies-data

公式ドキュメントによると、CloudSearchドメインの作成には通常およそ10分かかります。

ドメインの作成状況は以下のコマンドで確認できます。

Terminal window
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アドレスからのみアクセスを許可するようにドメインのアクセスポリシーを更新します。

Terminal window
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)を使用します。以下はインデックスフィールドを定義するコマンドの例です。

Terminal window
aws cloudsearch define-index-field \
--domain-name searching-movies-data --name adult --type text
aws cloudsearch define-index-field \
--domain-name searching-movies-data --name belongs_to_collection --type text
aws cloudsearch define-index-field \
--domain-name searching-movies-data --name budget --type double
aws cloudsearch define-index-field \
--domain-name searching-movies-data --name genres --type text
aws cloudsearch define-index-field \
--domain-name searching-movies-data --name homepage --type text
aws cloudsearch define-index-field \
--domain-name searching-movies-data --name id --type int
aws cloudsearch define-index-field \
--domain-name searching-movies-data --name imdb_id --type text
aws cloudsearch define-index-field \
--domain-name searching-movies-data --name original_language --type text
aws cloudsearch define-index-field \
--domain-name searching-movies-data --name original_title --type text
aws cloudsearch define-index-field \
--domain-name searching-movies-data --name overview --type text
aws cloudsearch define-index-field \
--domain-name searching-movies-data --name popularity --type double
aws cloudsearch define-index-field \
--domain-name searching-movies-data --name poster_path --type text
aws cloudsearch define-index-field \
--domain-name searching-movies-data --name production_companies --type text
aws cloudsearch define-index-field \
--domain-name searching-movies-data --name production_countries --type text
aws cloudsearch define-index-field \
--domain-name searching-movies-data --name release_date --type text
aws cloudsearch define-index-field \
--domain-name searching-movies-data --name revenue --type int
aws cloudsearch define-index-field \
--domain-name searching-movies-data --name runtime --type double
aws cloudsearch define-index-field \
--domain-name searching-movies-data --name spoken_languages --type text
aws cloudsearch define-index-field \
--domain-name searching-movies-data --name status --type text
aws cloudsearch define-index-field \
--domain-name searching-movies-data --name tagline --type text
aws cloudsearch define-index-field \
--domain-name searching-movies-data --name title --type text
aws cloudsearch define-index-field \
--domain-name searching-movies-data --name video --type text
aws cloudsearch define-index-field \
--domain-name searching-movies-data --name vote_average --type double
aws cloudsearch define-index-field \
--domain-name searching-movies-data --name vote_count --type int

設定が完了したら、検索ドメインにドキュメントのインデックス作成を開始するよう指示します。

Terminal window
aws cloudsearch index-documents \
--domain-name searching-movies-data

データセットのインデックス作成

Kaggleからデータセットをダウンロードし、先頭1,000行からなるサンプルファイルを用意します。

Terminal window
head -1000 movies_metadata.csv > sample.csv

CloudSearchはコンソール画面からCSVファイルを直接インデックスできますが、AWS CLIのaws cloudsearchdomain upload-documentsコマンドはJSONまたはXML形式のみを受け付けます。

Actions > Upload documentsに移動します。

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

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

処理が完了すると、(ヘッダーを除く)998件のレコードが正常にインデックスされたことを確認できます。

クエリの実行

テキスト検索

titleフィールドとoverviewフィールドに対して、キーワードhouseで映画を検索します。

Terminal window
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_average5.0の映画を検索します。

Terminal window
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_average7.0より大きい映画を検索します。

Terminal window
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"
}
},
...
]
}
}

詳細については公式ドキュメントを参照してください。

クリーンアップ

作業が終わったらドメインを削除します。

Terminal window
aws cloudsearch delete-domain \
--domain-name searching-movies-data

まとめ

公開されている映画データセットの998行をAWS CloudSearchにインデックスしてクエリを実行したところ、別途検索クラスタを管理することなく、同一ドメイン上で全文検索と数値検索の両方が機能することを確認できました。q=houseのようなクエリと、q.parser=structured&q=vote_average:[7.0,}のような構造化パーサーを切り替えるだけで、追加の設定なしに全文検索と数値範囲検索の両方をカバーできる点が、CloudSearchの便利なところです。CloudSearchのエンドポイントはデフォルトでパブリックインターネットからアクセス可能なため、update-service-access-policiesを使ってドメインのアクセスポリシーを特定のaws:SourceIpに制限する作業は、ドメイン作成直後に行っておく価値があります。ドメイン作成に約10分かかる点も、より大きなセットアップ手順の一部としてスクリプト化する場合には考慮しておくべきでしょう。

About the author

Takahiro Iwasa

Takahiro Iwasa

Software Developer

This blog shares technical notes from hands-on projects—architecture, implementation, and AWS service integrations.