クラウドワークス エンジニアブログ

日本最大級のクラウドソーシング「クラウドワークス」の開発の裏側をお届けするエンジニアブログ

Elasticsearch RailsからSearchkickへの移行で気づいたSearchkickの注意点

こんにちは、クラウドソーシングサービス「クラウドワークス」でエンジニアをしている神山です。クライアントとワーカーのマッチングに関わる機能の運用・改善を行うデリバードチームに所属しています。

本サービスではRails環境での検索エンジン運用に Elasticsearch Rails を使用してますが、この度 Searchkick への移行を決定し、現在移行作業中です。この移行作業を通じて、Elasticsearch RailsとSearchkickの間にはいくつか顕著な違いがあり、特にElasticsearch Railsからの移行に際して注意が必要な点がいくつか存在しました。今回はその点を中心に書きました。

Searchkick移行の背景

趣旨とは逸れるため簡潔に書きますが、検索エンジンElasticsearch から OpenSearch へ移行する予定があり、Elasticsearch RailsではOpensearchに対応していないためSearchkickに移行することを決めました。(他のGemも候補にありましたが選定理由は省略いたします。)

またElasticsearch RailsがElasticsearch8に対応していなかったこともGemを移行したい理由の一つにありましたが、それがSearchkick移行の大きな要因ではありません。そのため2024年4月16日にElasticsearch RailsはElasticsearch8に対応した v8.0.0.pre をリリースし2024年5月31日に v8.0.0 をリリースしておりますが、Searchkick移行は継続して行っております。

移行の際に気付いたSearchkickの注意点

Searchkickではデータ作成や更新時のコールバック処理がデフォルトで作動する

Elasticsearch Railsの場合、Elasticsearch::Model::Callbacksをモデルに明示的にインクルードしない限り、データ作成や更新の際にElasticsearchのインデックスに対する処理は発生しません。 しかし、Searchkickではデフォルト設定でRailsafter_commit コールバックにインデックスへのドキュメントの追加などの処理を含めます。これによりElasticsearchへのリクエストが増加したり、意図しないデータ更新が自動的にインデックスされるため、その挙動を理解しておいたほうが良さそうです。

github.com

以下のように callbacks オプションを false に設定すると、コールバック処理を行わなくなります。

class Job < ApplicationRecord
  searchkick callbacks: false

  # ...
end

Searchkickが用意しているインデックス生成メソッドの挙動が想像と少し違う動きをした

SearchkickではSearchkick::Index#createSearchkick::Index#create_indexの2つのインデックス生成メソッドを提供しています。

Searchkick::Index#createElasticsearch::API::Indices::IndicesClient#createをそのまま使用します。しかしマッピングやセッティングなどの設定をモデルに記述していても反映されないため、必要な設定を引数に渡す必要があります。

github.com

一方Searchkick::Index#create_indexはモデルに記述した設定を反映してインデックスを作成しますが、インデックス名がタイムスタンプを含んだ特定の形式("#{name}_#{Time.now.strftime('%Y%m%d%H%M%S%L')}")になってしまいます。これはインデックス名の重複を防ぐのに役立ち、インデックス名の形式を統一できる利点がありますが、既存のインデックス名との整合性を保つためには注意が必要です。

github.com

私個人としてはモデルに記載した設定を素直に反映しインデックス名は任意の値にしたかったので、この2つのメソッドを扱うのは少し苦労しました。

Searchkick::Index#all_indices はすべてのインデックスを取得しない

Searchkick::Index#all_indicesは、モデルに関連するすべてのインデックス名の配列を取得する便利なメソッドのように見えます。しかし特定の正規表現パターン( /\A#{Regexp.escape(name)}_\d{14,17}\z/ )にマッチするインデックス名のみを取得します。 この正規表現パターンは、Searchkick::Index#create_indexで作成したインデックス名に適用されますが、Elasticsearch Railsから移行する際には、この命名規則に従っていないインデックスが存在する可能性があるため使用には注意が必要です。

github.com

またSearchkick::Index#full_reindexSearchkick::Index#clean_indicesも内部で all_indices を使用しているため、この形式のインデックスにしか対応していない点に留意してください。

Searchkickに用意されてある reindex メソッドはReindexAPIとは別物

Searchkickには reindex という名前のメソッドがいくつかあります。名前からしてElasticsearchの ReindexAPI を彷彿とさせますが、ReindexAPIを内部で使用していることもなく、処理の内容も全く異なります。

特にREADMEにもある Product.reindex のようなSearchkick::Model.reindexを使う際には注意が必要です。内部で Searchkick::Index#reindex に処理を委託していますが、このメソッドはモデルに関連するインデックスを一度すべて削除する処理が含まれます。消す必要のないインデックスを削除してしまったり処理コストが増大する恐れがあるため、使用の際にはコードをよく確認することをおすすめします。

github.com

github.com

ちなみに Searchkick::Index#reindex には以下のようなコメントがあるので、アプリケーションでの使用は避けた方が良いかもしれません。

# reindex
# note: this is designed to be used internally
# so it does not check object matches index class
def reindex(object, method_name: nil, full: false, **options)

Searchkickの魅力的な点

ここまではSearchkickの注意点を挙げてきましたが、Searchkickは魅力的なところも沢山あります。私が感じた魅力を一部取り上げてみました。

メンテナンスが頻繁に行われている

SearchkickのCommitsを見ると、継続的にメンテナンスされていることが確認できます。今年に入ってから新バージョンのリリースはありませんが、継続的にコミットされているため安心感があります。

ライブラリのメンテナンス状況は使用するか否かにおいて非常に重要な判断基準となります。その点で、頻繁にメンテナンスが行われている点は大きいです。

Elasticsearch RailsはElastic社のOSSであるためそこの安心感はありますが、長い間メンテナンスされていなかったことが大きな不安要素でした。Elasticsearch8対応を機に、引き続きメンテナンスが行われるかは気になるところです。

便利なインターフェースが用意されている

例えばSearchkickが提供するインターフェースの一つに、Searchkick::Index#promoteがあります。これはエイリアスの貼り替えを行ってくれるメソッドで、インデックスを複数運用するにあたってとても有り難いです。

github.com

また、Searchkickでは Searckick::Index#bulk_indexSearckick::Index#bulk_updateSearckick::Index#bulk_delete など、Elasticsearchの Bulk API を利用しやすくなっています。こちらも頻繁に使用しております。

github.com

他にも多数の便利なメソッドが用意されており、SearchkickはRailsから検索エンジンを非常に扱いやすくしてくれています。また、様々な機能開発リクエストが起票されており、今後もさらに使い勝手が良くなることが期待されます。

ライブラリを使用する際、自前実装を避けてライブラリに依存する方が効率的なことが多いです。その点で多様なインターフェースを提供してくれるSearchkickには非常に助かっております。

おわりに

今回はSearchkick移行時の注意点を中心に書きましたが、Searchkickが劣っている、または優れているという話ではなく、Elasticsearch Railsとは異なることを伝えられていたら幸いです。個人的な感想としては、Searchkickはシンプルで使いやすいと感じております。 Searchkickの使用を検討している方は、ぜひ一度コードを読んで見てください。非常に読みやすくコード量も少ないため、Gemを読む練習としても最適です。

この記事が、Elasticsearch RailsからSearchkickへの移行を検討している方や、Searchkickの使用を考えている方にとって参考になれば幸いです。

© 2016 CrowdWorks, Inc., All rights reserved.