ScalaでElasticsearchを使う(elastic4s)
Posted: 2019-11-27
ScalaでElasticsearchを扱うライブラリelastic4sについて、比較的古めの情報しか見つからなかったので、使い方をまとめておきます。HTTPのAPIを提供するサーバーを作るコードを使って解説していきます。完全なコードはpecorarista/elastic4s-exampleを参照してください。
elastic4sを使う理由ですがAlpakka
Elasticsearchと違い、日本語の文字を使ったクエリに対応できていたからです。ただAlpakka ElasticsearchにPRを出したところマージされたので、今後のリリースでは解消されると思います。elastic4sとAlpakka
Elasticsearchの違いとしては前者がDSLを使ってクエリを作ることが挙げられます。ここらへんは好みが分かれるところだと思いますが、個人的にはDSLを使う方が好きなのでelastic4sを使うことにしてよかったです。
Elasticsearchの準備
elastic4sのバージョンと整合性をとる必要があるため、今回は7.3.2をインストールします。インストール方法についてはよい解説がたくさんあるため、ここでは特に説明しません。
今回使うデータの仕様を定義したindex.json
を準備します。retrieved
(取得日時)はUNIX Timeを表す整数です。
これを使用してインデックスを作成します。
次に登録するデータを準備します。ここではbulk APIを使うので、以下のような形式のファイルを作成します。
これを以下のコマンドでElasticsearchに送ります。
依存関係の定義
elastic4sのREADMEを参考にbuild.sbtを編集します。今回はHTTPサーバーの機能を使うのでAkka HTTPの関連するライブラリも依存関係に含めます。このときelastic4sのメジャーバージョン・マイナーバージョンがElasticsearchのそれと一致するように気をつけてください。
Scalaでのデータ型の定義
まずは型クラス(case class)を定義します。今回はGETリクエストによる検索と、POSTリクエストによる更新のみの単純なAPIを作るので、以下の2つの型クラスを定義すれば十分です。
次にJSONをScalaの型クラスに変換する方法を定義します。elastic4sは以下のライブラリをサポートしているので好きなものを使ってください。今回はSpray Jsonを使います。これはAkka HTTPがSpray Jsonをサポートしているため、自分でコードを書く量が減らせるからです。
- Jackson
- Circe
- Json4s
- PlayJson
- Spray Json
今回はJSONとScalaにおける型が1対1で対応するため、jsonFormatN
を指定するだけで自動的に変換規則が生成されます。jsonFormatN
のN
は型クラスのフィールド数に合わせる必要があります。
クエリの組み立て方
elastic4sのドキュメントはやや古くなっている箇所が多いのでelastic4s/src/main/scala/com/requests/searches/queriesのあたりを参考にしながら書くとよいと思います。
ルーティング規則の定義
Akka HTTPのドキュメントを参考に、ルーティング規則を書いていきます。またAPIを提供するときオリジン間リソース共有 (CORS)について制御する必要が生じると思うので、cors()
を呼んでいます。今回の範囲では特に必要ではないので省いても大丈夫です。
実行
サーバーを起動するため、実行可能なオブジェクトを作成します
Scala側でサーバーを起動する前に、Elasticsearchが9200番のポートでアクセス可能なことを確認します。それができたらsbt
コマンドで対話環境に入り、run
と打ってHTTPサーバーを起動します。ここまでできたら、ブラウザのアドレスバーにhttp://localhost:8080/documents?term=...
(...
の部分は好きな文字列)と入力すると、検索結果が返ってくるはずです(termクエリなので単語の分かち書きを考慮した検索になっていることに注意してください。)。また更新については以下のようなPOSTリクエストを投げると“Success!”と帰ってくるはずです。もう一度検索し、タイトルが更新されていることを確認してみてください。