こんにちは!Eight事業部でサーバーサイドエンジニアをしている常盤です。
今回は、Eight が提供しているダイレクト採用プラットフォームである Eight Career Design (ECD) の検索機能を検索エンジンの Elasticsearch を利用して刷新した話をしたいと思います。
ECDの候補者検索機能とは
ECD とは、Eight を利用されている方と、自社にマッチする人材を採用したい企業の出会いをサポートするサービスです。詳しくはこちらの記事で紹介されています。
buildersbox.corp-sansan.com
ECD の機能の中でも、企業の担当者が Eight 内のスカウトを希望しているユーザーを検索してスカウトメッセージを送ることができる「候補者検索機能」は非常に重要な位置を占めています。
ECDの候補者検索機能が抱えていた課題
しかしながら、従来の候補者検索機能は歴史的経緯により RDB (Amazon Aurora MySQL) を用いて実装されていたために、以下のような問題を抱えていました。
- キーワード検索のような柔軟な検索ができず、職種や年齢等によるフィルタリング機能しかない (= 精度の問題)
- 検索クエリが重いため、レスポンスに平均3秒前後かかってしまう (= 速度の問題)
- 検索に用いるカラムの追加のたびにインデックス等によるパフォーマンスチューニングの必要がある (= 開発・運用コストの問題)
これらの課題を全て解消するため、検索システムを従来の RDB から全文検索に特化した検索エンジンである Elasticsearch に全面移行することを決めました。
Elasticsearch とは?
Elasticsearch とは、Apache Lucene をベースにした言わずと知れた全文検索エンジンです。以下のような特長により、高速でスケーラブルな検索システムの構築に役立ちます。
- 転置インデックスを自動で構築するため、高速な検索が可能
- クラスタの構築により、大規模データに対してもスケールアウトで対応可能
- RESTful API や柔軟なクエリ構文を提供しているため、効率的な開発が可能
転置インデックスとは、検索対象となる単語などの値 (term) をキーとして、それを含むドキュメントへのマッピングを保持するようなデータ構造です。詳しい説明は割愛しますが、こちらの記事などで詳しく解説されています。
www.elastic.co
Elasticsearch のドキュメントに保存できるデータ型は文字列以外にも数値や位置情報などがあり、転置インデックスによる高速な検索やソーティングが可能です。
Eight ではすでに名刺検索機能にて Elasticsearch の利用実績があり、ECDでも採用することにしました。
Elasticsearch を利用した新候補者検索機能の設計と実装
Elasticsearch を利用した検索システムを実装するにあたっては次の3つの問いがあり、それぞれ技術選定・設計を行う必要がありました。
- Elasticsearch のクラスタを稼働させるインフラをどう構築するか?
- Elasticsearch の RESTful API と Eight のアプリケーション (Ruby on Rails) の連携をどう実装するか?
- Eight の採用候補者データ (Aurora) を Elasticsearch にどのように同期するか?
それぞれの問いに対して、私たちがどのようなアプローチで解決したかをご紹介したいと思います。
Elasticsearch クラスタの構築
Eight では AWS を利用してインフラの構築を行っているため、Elasticsearch クラスタの構築方法としては大きく以下の3つの選択肢がありました。
- AWS のマネージドサービス Amazon Elasticsearch Service (以下、AES) を利用する
- Elastic社が提供するマネージドサービス Elastic Cloud を利用する
- EC2 インスタンスを用いて自前でクラスタを構築・運用する
私たちから見たそれぞれの選択肢のメリット・デメリットは以下でした。(前提として、チーム内での Elasticsearch の本格的な運用経験はありませんでした)
メリット | デメリット | |
---|---|---|
AES | ・構築や運用が簡単 ・AWSプラットフォームとの親和性が高い |
・プラグインや X-Pack の利用等に制限がある ・Elasticsearch の最新バージョンがすぐに利用できない |
Elastic Cloud | ・構築や運用が簡単 ・Elasticsearch の最新バージョンが利用でき、プラグインや X-Pack の利用もしやすい |
私たちのユースケースでは AES と比べて費用が高かった |
EC2 | プラグインや X-Pack はもちろん、全ての設定を自由にカスタマイズできる | 構築や運用を自前で行うため工数がかかる |
これらの要素を比較検討した結果、今回は AES を採用することにしました。具体的には以下のような理由によります。
- 構築・運用工数を削減し、スピーディかつ安全にリリースすることを優先したかった
- 当面の間は、プラグインの追加など AES において制限を受ける機能を必要としなそうだった
Ruby on Rails アプリケーションとの連携
Eight の Ruby on Rails アプリケーションと Elasticsearch 間の通信処理の実装方法には、以下の2つの選択肢がありました。
- 公式のgem elasticsearch-ruby / elasticsearch-rails を利用する
- 自前で Elasticsearch の RESTful API のクライアントを実装する
当初は前者の gem を利用した方針をとる予定でしたが、実は Eight にはすでに Elasticsearch 5系用の gem がインストールされており、私たちが使おうとしている 7系の gem と衝突してしまう問題がありました。加えて以下のような理由もあり、gem を使わず自前でAPIクライアントを実装しました。
- 特定の gem にロックインすると、今後のアップデートなどへの影響が懸念される
- 実装にあたって Elasticsearch 本体以外に gem のドキュメントの参照も必要になってしまう
候補者データの同期処理
最後に、Aurora から Elasticsearch へのデータ同期処理まわりについてご紹介します。ECD における同期処理は、以下の2種類に大別されます。
- 候補者のプロフィールなど、リアルタイムに変化するデータを同期するストリーム処理
- 機械学習による推定データ (職種など) のように、定期的に更新されるデータを同期するバッチ処理
まず1つ目のストリーム処理は、Aurora のデータが更新されるたびにジョブを SQS に積み、ECS 上のワーカープロセス (shoryuken gem) で更新処理を行うという構成にしています。ジョブのキューイングや ECS のオートスケーリングにより、データの更新数が増えてもパフォーマンスに問題なく処理を捌くことができます。
次に2つ目のバッチ処理では、データ統括部門である DSOC が機械学習等により定期的に生成する推定データを Elasticsearch に同期しています。ここでは大量のデータを効率良く更新する必要があるため、Elasticsearch の Bulk API を利用して複数のドキュメントを一度のリクエストにまとめて処理するようにしました。
Elasticsearch への移行による成果
今回の機能刷新により、企業が自社にマッチする候補者をより速く、正確に検索することができるようになりました!具体的には、以下のような成果がありました。
- 候補者検索からの Talent Pool (気になる候補者のピン留め機能) への追加数が4割程度向上した
- 検索のレスポンスが平均3秒程度から1秒程度に短縮された
- 検索項目の追加や検索クエリの調整などの改善がより柔軟にできるようになった
Elasticsearch には検索のための数多くの機能があり、細かいチューニングを行うことで検索精度やパフォーマンスを高めることができます。今後も Elasticsearch を活用して、より人材を見つけやすいサービスを作っていきたいと思います💪
buildersbox.corp-sansan.com
buildersbox.corp-sansan.com
buildersbox.corp-sansan.com