Speeee Advent Calendar 8日目です。
ここ約3ヶ月ほど全く触ったことのないElasticsearchを使うプロジェクトにアサインされ、よくわからんことだらけだった中でネット上に日本語であまり見当たらなかったような気がしたelasticsearch-persistence
について軽くまとめられればなーと思っております。
使用してる環境
elasticsearch(1.7.2)
elasticsearch-persistence (0.1.8)
rails(4.2.3)
ruby(2.2.3)
なぜpersistenceを使ったのか
アプリケーションにテーブルの存在するモデル(ActiveRecordを継承したモデル)にelasticsearchによる検索を適応する場合には、Elasticsearch::Model
を利用することで、そのモデルにelasticsearchの機能が付与することができます。
ただ、今回私が携わってきたプロダクトではテーブルが存在しないモデル(ActiveRecordを継承しないモデル)でelasticsearchを使った検索をしたかったためpersistenceを使うことにしました。
Elasticsearch::Persistenceの2つの実装方法
persistenceには
- Repositoryタイプ
-
Active Recordタイプ
があります。
Repositoryタイプ
この場合はrepositoryがelasticsearchへの検索、参照、保存、削除などを担っており、repositoryへsaveメソッドの引数として値の入ったモデルを入れることにより、保存してくれたりします。
repositoryパターンを提供したものであるようです。
ActiveRecordタイプ
こちらは文字通りActiveRecordのモデルと同じ感覚でElasticsearchの検索などを使えるようにするものです。
今回はこちらを採用しました。
理由はいつものrailsっぽく使えるから、という理由のみです。
ModelとRepositoryの関係
ActiveRecordタイプで実装するものでも、内部的にはRepositoryを使っていて、その利用が隠蔽されているだけに過ぎないので、例えばElasticsearch::Persistence::ModelをincludeしたHogeモデルがあるとすると
Hoge.gateway
にElasticsearch::Persistence::Repositoryが格納されています。
Elasticsearch::Persistence::Modelの使い方
include Elasticsearch::Persistence::Model
ってモデルに書けばOK
Elasticsearch::Persistence::Model
自体はvirtusとActiveModelが入っているのでこれ入れるだけで基本的なモデルがかけます。
class Hoge
include Elasticsearch::Persistence::Model
attribute :fuga, Integer
validates :fuga, presence: true
end
こいつに.save
とかやれば保存してくれたり、.search(#{query})
とかやれば検索してくれて検索結果を取得できます。
検索結果として戻ってくるのはElasticsearch::Persistence::Repository::Response::Results
ですが、eachなどで展開すると直接呼び出したモデルに格納された状態で操作できます。
直接呼び出したモデルなので、例えば親クラスでのみincludeしておいて、その小クラスで検索した場合には親クラスに格納された結果になるので少し注意が必要です。
また、aggregationを利用した場合にはこの限りではないので、直接値を掘り出して、モデルに格納するなどの操作が必要です。
indexとdocumentの指定方法
index_name 'hoge'
document_type 'fuga'
と書けばOK
書かないとクラス名から推測されて勝手に作られます。
module Elasticsearch
class Hoge
include Elasticsearch::Persistence::Model
index_name 'hoge' # add
document_type 'fuga' # add
attribute :fuga, Integer
validates :fuga, presence: true
end
end
indexの強制更新
よくelasticsearchを実際に使ったrspecなどのテストでelasticsearchにデータ入れた後すぐ反映したい場合、
{Elasticsearch::Model}.__elasticsearch__.create_index!
{Elasticsearch::Model}.__elasticsearch__.flush_index!
と書きますが、persistenceの場合は
{Elasticsearch::Persistence::Model}.gateway.create_index!
{Elasticsearch::Persistence::Model}.gateway.flush_index!
となります。
つまり、persistenceの場合には__elasticsearch__
に対応するのがgateway
になるので、Elasticsearch::Model
を使っている記事の__elasticsearch__
をgateway
に読み替えれば結構いけること多いです。
hostを環境毎に変更する
めっちゃ普通
Elasticsearch::Persistence.client = Elasticsearch::Client.new(host: ENV['ELASTICSEARCH_HOST'], logs: Rails.env.development?, trace: Rails.env.development?)
これはほとんどElasticsearch::Model
の記事を参考にさせていただきました。
参考: RSpecでElasticsearchを使ったテストを書く
おわりに
persistenceを使った場合の本当に基本的なところと、Elasticsearch::Model
とちょっと違うところをまとめました。
当時は右も左も分からない状態で疑う箇所が多かったので、直接persistenceを使った記事少なくて困ったなーと思っていましたが、今になってみると結局要点を抑えればElasticsearch::Model
を利用した記事を参考にすれば良いということです。