patorashのブログ

方向性はまだない

RailsでElasticsearchを使う際のレスポンスはidだけ返せばよかった

表題の通りですが、今まで運用していて全然気づかなかったことでした。

Elasticsearchにクエリを投げると、ヒットした際にレスポンスがめっちゃ長くてdevelopment.logが見づらくなってました。 ログをよく見ると、レスポンスからrecordsメソッドを呼ぶと、ヒットしたデータのIDの配列でデータベースから再取得していたので、「あれ?これってもしかしてElasticsearchからのレスポンスってIDだけでいいんじゃない?」と思ったので、早速実験してみました。

ちなみに、これがその処理。

elasticsearch-rails/active_record.rb at v7.1.1 · elastic/elasticsearch-rails · GitHub

elasticsearch-dslでクエリを組み立てる

Postモデルがあるとして、Elasticsearchに既にデータ登録されているとします。 elasticsearch-dslを使って、sourceメソッドで取得フィールドを指定します。

definition = Elasticsearch::DSL::Search::Search.new
definition.query do
  # 検索条件を設定
end

# sourceメソッドで取得するフィールドを配列で指定する
definition.source([:id])

# ElasticsearchでヒットしたデータのIDから、データベースに取りに行く
posts = Post.__elasticsearch__.search(definition.to_hash).records

こうすると、ElasticsearchからのレスポンスはIDのみとなり、通信量が激減しました!😀はいえ、問題は、ちゃんとRailsで動くかどうかです。

テストの実行結果

担当プロジェクトのElasticsearch関連のテストを実行してみたのですが(見せられませんが…)、recordsメソッドでデータベースデータを取得し直しているので、テストも全て通って問題なし!しかもElasticsearchのレスポンスが減ったからか、テストの速度も若干改善しました🚀

Elasticsearchからのレスポンス自体を活用するには?

あんまりちゃんと調べてないけど、たしかrecordsメソッドではなく、resultsメソッドを使えばいいはず…。しかし、その際にはこの方法だとidしかないので、微妙です。でも、データベースへの問い合わせがないぶん、早いはず。ActiveRecordのモデルは使えないと思うけど。

elasticsearch-rails/response.rb at v7.1.1 · elastic/elasticsearch-rails · GitHub

画面で動作確認

本番環境と同等のマスタデータを搭載して、developmentモードで画面から検索をかけてみたところ、レスポンスが1秒近く改善しました。😯めちゃくちゃ効果あるやん…。1秒ではなかったです…。たまたま遅い時を引いてしまったぽかった。でもまぁ50ms〜150msくらい速くなりました。

まとめ

RailsでElasticsearchを使っている場合にrecordsメソッドを使っている場合は、Elasticsearchからのレスポンスはidだけあればいいので、idのみで取得しても問題なさそう。むしろ通信量が減って速度改善するしよさそう。