Amazon CloudSearch で 商品検索を実現する - No.1 データ投入

# やりたいこと
RDSMSのLIKE検索よりも柔軟に、検索エンジンの要領で商品検索を行うことを目標にします。

# 環境
* Amazon CloudSearch APIバージョン **2013-01-01** 

# 利用するデータ
Wikpediaの[任天堂発売のゲームタイトル一覧](https://ja.wikipedia.org/wiki/%E4%BB%BB%E5%A4%A9%E5%A0%82%E7%99%BA%E5%A3%B2%E3%81%AE%E3%82%B2%E3%83%BC%E3%83%A0%E3%82%BF%E3%82%A4%E3%83%88%E3%83%AB%E4%B8%80%E8%A6%A7)ページのリンク先をスクレイピングしてjson形式のデータを作成します。

```json:
[
    {
        "type": "add",
        "id": 1,
        "fields": {
            "page_title": "マリオブラザーズ",
            "content": "『マリオブラザーズ』は、1983年に発売された任天堂のアクションゲーム。マリオシリーズで初めてマリオの名がタイトルに冠され、マリオという名として主人公が活躍するゲームとしては、マリオシリーズ第1作目にあたる。",
            "genre": "固定画面アクションゲーム",
            "plat": "アーケード",
            "dev": "任天堂",
            "pub": "任天堂レジャーシステム",
            "producer": "横井軍平",
            "designer": "宮本茂",
            "programmer": "宮本茂",
            "composer": "兼岡行男",
            "players": "1 - 2人",
            "media": "業務用基板",
            "working_dates": "1983年7月14日1983年",
            "rating": "CERO：A（全年齢対象）",
            "device": "2方向レバー 1ボタン",
            "cpu": "メイン：Z80 (@ 3.072 MHz) サウンド：I8039 (@ 730 kHz)",
            "sound": "DAC",
            "display": "ラスタースキャン 横モニター 256 x 224ピクセル パレット256色",
            "etc": "移植されたプラットホームについては本記事#他機種版の項を参照のこと。",
            "link_title": "マリオブラザーズ"
        }
    },
～以下省略～
```

JSONファイルのフィールドは[Amazon CloudSearch 用にデータを準備](https://docs.aws.amazon.com/ja_jp/cloudsearch/latest/developerguide/preparing-data.html)に沿って作成します。
<dl>
<dt>type</dt><dd>実行するオペレーション: add または delete。</dd>
<dt>id</dt><dd>ドキュメントの一意の ID。ドキュメント ID では、任意の英字または数字と次の文字を使用できます。​_ - = # ; : / ? @ & ドキュメント ID は、1​～​128 文字以内にする必要があります。</dd>
<dt>fields</dt><dd>各ドキュメントフィールドの名前と値のペア。latlon フィールドの値を指定するには、カンマ区切りリストとして緯度と経度を指定します。たとえば、"location_field": "35.628611,-120.694152" のようになります。ドキュメントを JSON で指定する場合、フィールドの値を null にすることはできません（ただしフィールドを完全に省略することはできます）。</dd>
</dl>
  

|フィルド名|内容|
|:----|:----|
|link_title|任天堂発売のゲームタイトル一覧のリンクのテキスト|
|page_title|リンク先のページのタイトル|
|content|最初の、目次の前の1段落の文章|
|genre|テンプレートに記載されているジャンル|
|plat|テンプレートに記載されている対応機種|
|dev|テンプレートに記載されている開発元|
|pub|テンプレートに記載されている発売元|
|distributor|テンプレートに記載されている販売元|
|producer|テンプレートに記載されているプロデューサー|
|director|テンプレートに記載されているディレクター|
|designer|テンプレートに記載されているデザイナー|
|writer|テンプレートに記載されているシナリオ|
|programmer|テンプレートに記載されているプログラマー|
|composer|テンプレートに記載されている音楽|
|artist|テンプレートに記載されている術|
|license|テンプレートに記載されているライセンス|
|series|テンプレートに記載されているシリーズ|
|ver|テンプレートに記載されているバージョン|
|players|テンプレートに記載されている人数|
|media|テンプレートに記載されているメディア|
|publish_date|テンプレートに記載されている発売日|
|last_release_version|テンプレートに記載されている最新版|
|last_preview_version|テンプレートに記載されている最新評価版|
|rating|テンプレートに記載されている対象年齢|
|contents_icon|テンプレートに記載されているコンテンツ アイコン|
|download_content|テンプレートに記載されているダウンロード コンテンツ|
|device|テンプレートに記載されているデバイス|
|spec|テンプレートに記載されている必要環境|
|engine|テンプレートに記載されているエンジン|
|aspect_ratio|テンプレートに記載されているアスペクト比|
|resolution|テンプレートに記載されている解像度|
|cabinet|テンプレートに記載されている筐体|
|cpu|テンプレートに記載されているCPU|
|sound|テンプレートに記載されているサウンド|
|display|テンプレートに記載されているディスプレイ|
|sales|テンプレートに記載されている売上本数|
|etc|テンプレートに記載されているその他|

# 検索ドメイン作成

検索する商品を投入するために **検索ドメイン** を作成します。 検索ドメインはRDSMSと対比させるとテーブルに近い概念ですが、一つのドメインには一つの定義を作成し、検索ドメインで検索対象のデータを定義します。CloudSearchは[Apache Solr](http://lucene.apache.org/solr/)のマネージドサービスなので、検索ドメインを Solrの言葉で表すと「スキーマ」になります。

Solrの「スキーマ」に由来するのでRDBMSでのJOINに相当することがでません。非正規化したデータを使います。

## ウィザードを起動して検索ドメインの情報を入力
### ウィザード起動
CloudSearchの管理コンソールから「Create a new search domain」ボタンをクリックして、ウィザードを起動します。
![00-start-wizard.png](https://qiita-image-store.s3.amazonaws.com/0/145742/0fc823fd-996a-affb-d2cd-22da2d275a23.png)

### NAME YOUR DOMAIN
**Search Doamin Name**に検索ドメイン名を入力します。今回は「cs-games」にしました。アップロード容量と検索性能の **Desired Instance Type**と耐障害性の**Desired Replication Count**はデフォルト値のままにします。

![01-create-domain.png](https://qiita-image-store.s3.amazonaws.com/0/145742/3b33d598-8f17-4643-aea4-08d6c954a907.png)

### CONFIGURE INDEX

ウィザードに投入するデータをアップロードすることでフィールド設定のひな型が提供されるので、スクレイピングで作成したjson形式のファイルをアップロードします。

![02-columnconfig.png](https://qiita-image-store.s3.amazonaws.com/0/145742/9038de56-a2a1-6c65-6b2e-7374b11aa950.png)

### REVIEW INDEX CONFIGURATION

アップロードされJSONを元にフィールド名の定義が自動作成されます。概ね、このまま利用しますが、二つだけ変更を行います。

* すべてのフィールドのAnalysis SchemeをJapaneseに変更します。
* distributor、genre、plat、pubのTypeを**literal**に変更し、**Facet**をonにしておきます。 ファセットは検索結果の絞り込みとフィルタ処理を行うために使用するカテゴリとして利用できます。

![03-review-configuration.png](https://qiita-image-store.s3.amazonaws.com/0/145742/4dc6321f-411e-d686-4853-feca1abcfcab.png)

### SETUP ACCESS POLICIES
検索ドメインのアクセスポリシーを設定します。今回は**Search and Suggester service: Allow all. Document Service: Account Owner only.**を選択します。

![04-access-policy.png](https://qiita-image-store.s3.amazonaws.com/0/145742/9fdb26f3-113e-a7af-4c01-1358beaeaaf4.png)

### CONFIRM
ここまでの設定内容を確認します。修正内容があれば、左下の**Back**を押下して戻ります。この内容でよければ、右下の**Confirm**を押下します。

![05.confirm.png](https://qiita-image-store.s3.amazonaws.com/0/145742/b57bf4cb-fd6b-49b9-1d85-5a6b8c3dffd0.png)

## ウィザード終了
Wizardで一通りの手続きが完了すると、インスタンスに検索ドメインが作成されます。作成には10分程かかるのでしばらく待ちます。

![06.done.png](https://qiita-image-store.s3.amazonaws.com/0/145742/46d05d3d-34a3-0692-6934-8a398c40486b.png)

## ダッシュボードで完了を待つ
管理コンソールから作成した検索ドメインのステータスが**ACTIVE**になるのを待ちます。

![07-active.png](https://qiita-image-store.s3.amazonaws.com/0/145742/bbb1a57b-6879-0880-c2b0-6eaf04cd8e6e.png)


# データ投入
## DOCUMENT SOURCE
ダッシュボードの**Upload Documents**を押下します。表示されるダイアログの**File(s) on my local disk**を選択し、投入するデータのjsonファイルを指定します。その後に**Continue**を押下します。

![1.choice-file.png](https://qiita-image-store.s3.amazonaws.com/0/145742/4d83ed0b-1f06-d71c-2737-7cfe9bff4d20.png)

## REVIEW DOCUMENTS
アップロードしたjsonファイルが読み込まれ、チェックが行われます。解析して得られた件数とフィールドが表示されます。もし、解析した結果にエラーがあれば、赤文字で表示されます。エラーがなければ**Upload Documents**を押下します。

![2.review.png](https://qiita-image-store.s3.amazonaws.com/0/145742/08fb3ce4-f5b1-bc7f-cb3c-0a0f8c929b37.png)

## DOCUMENT SUMMARY
アップロードが無事に終わると、サマリーとして追加と削除の件数が表示されます。
最後に**Finish**を押下して、ダイアログを閉じます。

![3.sumary.png](https://qiita-image-store.s3.amazonaws.com/0/145742/dfb817c8-9c77-b95c-ea38-86303214e715.png)

# 簡単な検索

ダッシュボードの**Searchable Documents**はアップロードしたJSONファイルの内容ににエラーが無ければ、JSONファイルに登録してあった件数と同じになっています。それを確認し、新しく表示されている**Run a test search**に検索ワードとして「マリオ」を入力し、**Go**を押下すると検索が行われます。

![a.searchFromDashboard.png](https://qiita-image-store.s3.amazonaws.com/0/145742/3764f95b-5f6f-9978-bce0-7168f26b2b2c.png)
↓
![b.searchResult.png](https://qiita-image-store.s3.amazonaws.com/0/145742/63d425f4-b610-ff2c-a42e-13194824229f.png)

ファセットに指定したganre、plat、pubで絞込を行えるように、検索結果の右側にフィールド毎に候補が表示されています。

# つつき(予定)

テキスト分析スキームの[シノニム](https://docs.aws.amazon.com/ja_jp/cloudsearch/latest/developerguide/configuring-analysis-schemes.html#synonyms)を試してみます。

シノニムを利用することで「FC」と「ファミコン」と「ファミリーコンピューター」を同じものを指す単語としてあつかえる予定です。