CloudSearchのインデックスフィールドの設定をJSONで

# はじめに
CloudSearchはAWSが提供しているクラウドサービスの一種で、SESとかSQSなどとともにApplication Servicesに分類されるサービスです。
フルマネージドなサービスで、検索機能を提供してくれます。

CloudSearchには検索ドメインという単位があり、検索ドメインには検索可能なデータが集まるコーパスと、検索用インスタンス群が含まれます。

ユーザーは自身が持っているデータをCloudSearchにアップロードすることで、(**事前に設定されたインデックスフィールドの設定**に基づいて) 検索対象であるコーパスを作成することができます。

インデックスフィールドの設定はAWSコンソールやAWS CLI、SDKを用いて行うことができます。
AWSコンソールを用いると簡単に設定を行うことが出来ますし、公式のドキュメントでも詳しく説明されています。

ですが、自前のサービスに組み込んで運用するためには、何度でも同じ設定を復元できるようにしておく必要があると考えます。
例えば設定手順書等を作ることでAWSコンソールからの設定をサポートすることはできますが、わりと高頻度で行われるUIの変更や個々人の能力に依存するという問題が残ります。

一方、AWS CLIを用いて設定を行うことも可能であり、コードとして設定を残すことが出来ます。
そうしておくと版管理も楽にできますし、だれが実施しても同じ結果を得ることが出来ます。

そのため、インデックスフィールドの設定はAWS CLIを用いてコードで解決することが望ましいと考えます。

# この記事の目的
上記の理由からインデックスフィールドの設定をAWS CLIを用いて行おうとしていたのですが、なかなかまとまった情報が見つからず、結構詰まってしまったので情報を残したいと思います。クライアントのバージョンは以下です。

```bat
 $ aws --version
 aws-cli/1.9.7 Python/2.7.9 Windows/8 botocore/1.3.7
```

# インデックスフィールドの設定
公式ドキュメントにあるように、下記のコマンドでインデックスフィールドの設定を行うことが出来ます。

```bat

aws cloudsearch define-index-field --domain-name ドメイン名 --name インデックス名 --type インデックスタイプ
```

少数のインデックスフィールドのみであれば上記でも問題ありませんが、インデックスフィールドが増えてきたり、設定内容が複雑になると可読性がかなり下がってしまいます。

そこで、JSONファイルで設定を用意しておいて、それを読み込んで設定が行えるようにします。たとえばこんな感じで設定ファイルを用意します。

```json:sample.json
{
  "IndexField": {
    "IndexFieldType": "text",
    "IndexFieldName": "client_name",
    "TextOptions": {
      "HighlightEnabled": true,
      "ReturnEnabled": true,
      "SortEnabled": false,
      "AnalysisScheme": "_ja_default_"
    }
  }
}
```

用意したJsonファイルを**UTF-8**で保存し、下記のコマンドを実行するとインデックスフィールドの設定を行うことが出来ます。
ちなみにShift-JISだとCloudSearchに読み込んだ時に**日本語が化けます**。

```bat
aws cloudsearch define-index-field --domain-name ドメイン名 --cli-input-json file://jsonファイル名
```

これを必要な分だけ実行することで複数のインデックスフィールドの設定をコードで行うことが出来ます。

例えばこんな感じです。
index_settingsフォルダの下に設定のjsonファイルがいくつか置かれている状態です。

```bat:configure.bat
for /f "usebackq" %%i in (`dir /B /S index_settings\*.json`) do (
    call aws cloudsearch define-index-field --domain-name %domain_name% --cli-input-json file://%%i
)
```

# Jsonの中身
`IndexField`の中に `IndexFieldType`, `IndexFieldName`, `TextOptions` というキーが出てきます。

## IndexFieldType
インデックスフィールドの型を選択します。
int型やlatlon型、text型などがあります。詳細はこちらです。

http://docs.aws.amazon.com/ja_jp/cloudsearch/latest/developerguide/configuring-index-fields.html

## IndexFieldName
インデックスフィールドの名前です。

## TextOptions
ここにはIndexFieldTypeで指定した型に対応したOptionsが入ります。IndexFieldTypeでtextが指定されているのでTextOptionsが入っています。

Optionsは下記の種類があります

* IntOptions
* DoubleOptions
* LiteralOptions
* TextOptions
* DateOptions
* LatLonOptions
* IntArrayOptions
* DoubleArrayOptions
* LiteralArrayOptions
* TextArrayOptions
* DateArrayOptions

基本のデータ型とArrayのついた配列型があるイメージです。

## Options
Optionsの中には各インデックスフィールドの詳細設定が入ります。

### FacetEnabled
検索結果をフィルタするためのフィールドの定義です。
CloudSearchコンソールで検索を行って右の方に出てくるFilterSearchResultsに出てくる内容です。

### ReturnEnabled
検索結果として表示するのもを設定します。
これを適切に絞り込むことで検索結果として得られるデータを小さくすることが可能です。
検索結果データの大きさは料金に関わるものなのでこれを適切に設定することはとても大切です。

### SearchEnabled
検索対象とするインデックスにはこれを設定します。

### SortEnabled
これが設定されているインデックスを基準として検索結果をソートできるようになります。

### 型と設定できる内容一覧
それぞれ設定できる内容はフィールドの型によって下記のように異なります。

```json:int
{
 "FacetEnabled" :true,
 "ReturnEnabled" :true,
 "SearchEnabled" :true,
 "SortEnabled" :true
}
```

```json:double
{
 "FacetEnabled" :true,
 "ReturnEnabled" :true,
 "SearchEnabled" :true,
 "SortEnabled" :true
}
```

```json:literal
{
 "FacetEnabled" :true,
 "ReturnEnabled" :true,
 "SearchEnabled" :true,
 "SortEnabled" :true
}
```

```json:text
{
 "HighlightEnabled" :true,
 "ReturnEnabled" :true,
 "SortEnabled" :true
}
```

```json:date
{
 "FacetEnabled" :true,
 "ReturnEnabled" :true,
 "SearchEnabled" :true,
 "SortEnabled" :true
}
```

```json:latlon
{
 "FacetEnabled" :true,
 "ReturnEnabled" :true,
 "SearchEnabled" :true,
 "SortEnabled" :true
}
```

```json:int-array
{
 "FacetEnabled" :true,
 "ReturnEnabled" :true,
 "SearchEnabled" :true
}
```

```json:double-array
{
 "FacetEnabled" :true,
 "ReturnEnabled" :true,
 "SearchEnabled" :true
}
```

```json:literal-array
{
 "FacetEnabled" :true,
 "ReturnEnabled" :true,
 "SearchEnabled" :true
}
```

```json:text-array
{
 "HighlightEnabled" :true,
 "ReturnEnabled" :true
}
```

```json:date-array
{
 "FacetEnabled" :true,
 "ReturnEnabled" :true,
 "SearchEnabled" :true
}
```

最後にインデックスの貼り直しが必要になりますので、下記を実行してインデックスを張りなおしたら完了です。

```bat

call aws cloudsearch index-documents --domain-name %domain_name%
```