LoginSignup
9
6

More than 5 years have passed since last update.

elasticsearch-railsでkaminariとincludesを組み合わせるとエラーになる問題を解決

Last updated at Posted at 2016-09-21

elasticsearchの返却値にincludesを通常のやりかたでかませるとエラーがでる。
bulletでN+1の警告が拾われないため、つい見逃しやすい。
備忘録的なメモ。

前提

elasticsearch_railsにはkaminariモジュールがあるため、
elasticsearchの返却値に下記のようにpageを加えてあげることで、
ページングを実現できる

app/controllers/sample_models_controller.rb
class SampleModelsController < ApplicationController
  def index
    @sample_models = SampleModel.__elasticsearch__.search({query_json}).page(params[:page]).records
  end
end

viewは下記のようにElasticSearchを意識することなく
ActiveRecordと同様、kaminariの一般的な実装方法で記述できる。
これによりページング機能が実現できる。
これはElasticSearch内にkaminariモジュールがあるため、それによって実現されている

app/views/sample_models/index.html.haml
- @sample_models.each do |sample_model|
  = sample_model.title

= paginate @sample_models

問題: .includesをつけようとすると..

だが、ActiveRecordライクに下記のようにしてしまうと、

app/controllers/sample_models_controller.rb
# NG例
class ModelsController < ApplicationController
  def index
    SampleModel.__elasticsearch__.search({query_json}).page(params[:page]).records.includes(:child_model)
  end
end

kaminariで下記のエラーが発生する

undefined method `total_pages' for #<SampleModel::ActiveRecord_Relation:0x00************>

.includes(:child_model) と記述してしまった時点で、
Elasticsearch::Model::Response::Recordsが、SampleModel::ActiveRecord_Relation
に変換されてしまい、ElasticSearchのkaminariモジュールに用意されたパラメータがそぎ落ちてしまうことが原因

解決策

elasticsearch_railsのrecordにoptionでincludesを引き渡せるようになっているので、
それを利用すればよい。

sample_models_controller.rb
# OK例
class SampleModelsController < ApplicationController
  def index
    SampleModel.__elasticsearch__.search({query_json}).page(params[:page]).records(includes: :child_model)
  end
end
9
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
6