searchkickで多対多のデータを同期的にインデックスさせる

  • 4
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

ElasticseachをRubyから扱えるようになるsearchkickというgemがある。

このgemには、例えばUserというモデルにデータが追加されるとそれと同時にElasticsearch側にそのインデックスを作ってくれる便利機能がある。

また、Userを親に持つAddressという子モデルがある場合も以下のように書くとUserに紐づくAddressが新規に追加されたとき同時にインデックスを作成してくれる。

class Address < ActiveRecord::Base
  belongs_to :user

  after_commit :reindex_user

  def reindex_user
    user.reindex
  end
end

1対1や多対1のような関連の時にはこのやり方でいいのだけど、多対多のときは少し工夫が必要になる。

例えば、
(親)Article
(中間)ArticleTagging
(親)Tag
のような多対多の構成の関連があったとき、Articleに紐づくTagが追加されたときにそのTagをインデックスしたいとする。

公式のやり方に則ると下記のようになるけれども、

class Tag < ActiveRecord::Base
  has_many :article_taggings
  has_many :articles, through: :article_taggings

  after_commit :reindex_article

  def reindex_article
    article.reindex
  end
end

これだとうまくいかない。

多対多でもうまく同期的にインデックスさせるためには、下記のように中間モデルに記述する。

class ArticleTagging < ActiveRecord::Base
  belongs_to :tag
  belongs_to :article
  after_commit :reindex # after_saveだとFactoryGirlを使っているときにコケる

  def reindex
    article.reload.reindex
  end
end

これでうまくいく。

【参考】