RailsアプリでElasticsearchを扱うならchewyがおすすめ

Twitterでツイートしたり、表参道.rbの懇親会では紹介していたけど、ブログに書いていなかったので今更ながらまとめておきます。

github.com

Chewyの利点

READMEを一通り読んでもらうと 最高に便利なのが分かる とは思うのですが、それだと身も蓋もないので個人的に良いと思ってる機能を3つだけ紹介します。

  1. 複数のストラテジ
  2. ゼロダウンタイムのインデックス更新に対応したrakeタスク
  3. Named scopes

1. 複数のストラテジ

Chewyにはデフォルトで複数のストラテジが用意されてあります。

  • :atomic: 一括でインデックスを登録する
  • :urgent: 1つずつインデックスを登録する
  • :bypass: インデックスに登録しない
  • :active_job: 非同期処理でインデックスに登録する( :sidekiq などを直接使う事も可能)
  • ...など

これらのストラテジは最初から良い感じに設定してあります。

また、一時的にストラテジを切り替えることもできます。

Chewy.strategy(:bypass) do
  City.popular.map(&:do_some_update_action!)
end

2. ゼロダウンタイムのインデックス更新に対応したrakeタスク

READMEから説明を引用して紹介します。

Performs zero-downtime reindexing as described here. So the rake task creates a new index with unique suffix and then simply aliases it to the common index name. The previous index is deleted afterwards (see Chewy::Index.reset! for more details).

要は、「新しいインデックスを作って、エイリアスで切り替えるとゼロダウンタイムで更新できる」というもので、これに対応したrakeタスクが標準で用意されています。 しかもrakeタスクは最初から並列実行に対応しています。

あと、フィールドに updated_at が含まれていれば chewy:sync のタスクでDBとElasticsearchの同期を簡単に行うことができます。 基本的には使わないのですが、何かしらの理由でデータ不整合が起きた時に簡単に修正できて便利です。

参考: https://github.com/toptal/chewy/blob/v5.0.0/lib/chewy/type/mapping.rb#L192

3. Named scopes

ChewyではActiveRecordのようにScopeを定義することができます。

class UsersIndex < Chewy::Index
  def self.by_name(name)
    query(match: { name: name })
  end
end

UsersIndex.limit(10).by_name('Martin')
#=> <UsersIndex::Query {..., :body=>{:size=>10, :query=>{:match=>{:name=>"Martin"}}}}>

これは検索機能のように複数の条件を組み合わせるときに便利です。

class UsersIndex < Chewy::Index
  def self.by_name(name)
    # 検索フォームに未入力の場合を考慮
    return all if name.blank?

    query(match: { name: name })
  end

  def self.in_followers(user)
    query(match: { follower_ids: user.follower_ids })
  end
end

UsersIndex.by_name(params.dig(:q, :name)).in_followers(current_user)
#=> <UsersIndex::Query {..., :body=>{:query=>{:bool=>{:must=>[{:match=>{:name=>"Martin"}}, {:match=>{:follower_ids=>[1, 2]}}]}}}}>

まとめ

RailsでElasticsearchを使う場合、elasticsearch-railsを選ぶ人が多いとは思いますが、是非Chewyも検討してみてください。

私は去年の11月にchewyを見つけたけど、READMEを読んでelasticsearch-railsからchewyへの乗り換えを決めました。