AWS CloudSearch を使ってみた
Elasticsearch を調べたあと、最近は CloudSearch も機能強化されて日本語の検索も簡単にできていることを知り、いろいろ試して使ってみました。 結果、すごく良さそうなので今開発中のプロジェクトで採用することにしました。
調査しつついろいろコツというか知っておくべき点があったのでメモを残しておきます。 Elasticsearch との比較という観点で調査・検証していたので、Elasticsearch をある程度知った状態で読んでいただいた方がいいかも。
CloudSearch と Elasticsearch の比較
- Elasticsearch ではシャード数は index 作成時に決定しなくてはならないが、CloudSearch なら自動でスケールアップしてくれる。
- 検索のパフォーマンスに関しては Elasticserch でもあとから replica 追加可能なのでスケールアウト可能。しかし、インデックス更新のパフォーマンスは上げられない。
- 日本語検索は両者とも ok
- 特定の条件を重要視したスコアリングなども両者とも ok
- CloudSearch の場合、インデックスの作成や構造を変更するとき (カラムの追加とか) にはかなり時間がかかる + 別途料金 (1GB あたり 0.98 USD) がかかるので注意が必要。
CloudSearch を使う上で知っておきたいこと
- 検索クエリの書き方は simple, structured, lucene, dismax の 4形式をサポートしている。単純に全カラムを対象に全文検索を行うなら simple クエリで十分だけど、いろいろ条件を複合して絞り込みを行うなら structured クエリが複雑だけど柔軟度が高そう。
- 検索結果のスコアリングに影響を与えない、"filter" クエリも structured クエリ書式で書くことができる。Elasticserch にもある機能。
rails から扱いたい場合は https://github.com/wellbredgrapefruit/asari の v1.0 ブランチがよさそうfq
パラメータにちゃんと対応していないのでちょっとつらかった。https://github.com/stevenjl/rawscsi を検証してみる。これもクエリの自由度に欠けるためダメ。- 結局 AWS SDK の 2.0 の pre 版を使うのがよさそう。 http://docs.aws.amazon.com/sdkforruby/api/index.html
- CloudSearch を使うとローカルで検証ができないのが辛いところ (chatwork では検証用に m1.small の CloudSearch インスタンスを立ち上げて使っているらしい: https://speakerdeck.com/tanakayuki/kai-fa-zhe-karamitacloudsearch?slide=16)
インデックスの更新について
- インデックスの更新は "add" と "delete" の2種類で、それぞれ JSON をアップロードすることで更新する。
- add は常に上書き更新となり、一部のカラムだけ更新とかはできない。
- 複数の add, delete の操作をまとめて送ることができて(その単位をドキュメントバッチと呼ぶ)、なるべくドキュメントバッチのサイズ上限である 5MB に近いデータを送るようにした方がパフォーマンスがいいらしい。
- 僕はいったん更新/削除用の json をデータベースに貯めておいて、一定時間おきに sidekiq で最大 5MB ずつのバッチに分けてアップロードしています。
- json 以外のデータもアップロードできるらしいけど、そのユースケースが自分にはないので調べてないです。
- インデックス上のドキュメントを識別するための id は ActiveRecord のオブジェクトの id でももちろん ok
料金体系
- 次の 4つで課金されます。 -> インスタンス料金、ドキュメントの更新、インデックスの再構築、データ転送
- うち、インスタンス料金以外はかなり安いので無視してもよさそう。
- ちなみに最低で 0.082 * 24時間 * 30日 = $59.04/月 くらい (マルチAZ無し)