Pairsの検索システムについて

Hiroki Kojima
Eureka Engineering
Published in
6 min readDec 17, 2019

この記事は「eureka Advent Calendar 2019」17日目の記事です。

16日目はPairs JP iOS Teamの木村(Muukii)による「SwiftUIに適したアプリケーション設計を思考する」でした。

こんにちは!こんにちは!
APIチームのコジマ(@__bsoo )です。

今回はPairsの検索システムについて、勉強会やブログで小出しにしてはいたのですが、全体像をまとめて紹介したことが無かったのでこの機会に紹介できればと思います。

※サービスの性質上内容を一部ぼかしている箇所があります。ご了承ください。

■ システム構成

まずは全体の構成について紹介します。

言語:Go 1.13
検索エンジン:Elasticsearch 6.4

Pairsの全体構成図から検索部分のみを抜粋
Pairsの全体構成図から検索部分のみを抜粋

Pairsの検索システムと呼んではいますがマイクロサービスではないので、Pairsアプリケーションの一部を抜粋しています。

こちらに関しては基本的には一般的なウェブアプリケーション構成だと思います。

Elasticsearchに関しては初期はAmazon Elasticsearch Serviceを利用していたのですが、現在はチューニングの都合上EC2での運用を行っています。

■ データ同期

Elasticsearchにデータを同期するのは2種類の機構が存在します。

  • 一定の間隔でログインしたユーザーを取得し同期するジョブ
  • プロフィール更新などのAPIから直接同期

基本的には定期実行ジョブによりBulk APIを利用したドキュメントの完全更新をするようにしています。ただしこの場合実際にプロフィールが変更されてからElasticsearch上のデータが更新されるまでに時間差が発生してしまいます。リアルタイムに更新を反映させたい項目の場合はUpdate APIを使用し、API上からドキュメントを部分更新を行っています。

■ 検索フロー

簡単にですが検索のフローをご紹介します。

  1. クライアントから送信された検索条件と、内部で定義されたスコアリングからクエリを生成
  2. Elasticsearchにクエリを投げて検索
  3. 非表示にすべきデータをフィルタリング
  4. レスポンス生成

スコアリングにはFunction Score Queryを利用しています。条件やスコアの重みなどを柔軟に指定することができます。

Pairsの検索基盤として肝なのが 3のフィルタリング部分です。
オンラインデーティングサービスの性質上、検索者自身と表示されるお相手との間には複数の関連(いいね送った、受け取った・マッチング・非表示している、されている・退会済み etc… )があり、それらの表示・非表示を全て適切にハンドリングする必要があります。

当たり前の内容ではあるのですが、表示すべきではない結果を誤ってでも表示されてしまうとサービス品質・お客様からの信用を大きく落としてしまう可能性もあるため得に重要としています。
Elasticsearchで検索するクエリでもフィルタリングを行っているのですがデータの量の問題や同期タイミングの問題で完全にはフィルタリングしきれていないため、3でさらにフィルタリングを行うようにしています。

■ スコアの計算

現在Pairsで利用している一部の検索スコアはリアルタイムで計算することが難しく、事前計算が必要となっているものがいくつか存在しています。
ものによってはユーザーの組み合わせの数だけ処理が必要になっているため全てを処理するために大量のリソースと速度が必要となります。そのためスコア計算に関してはLambdaを利用しています。

Lambdaでのスコア計算システム構成
  1. Job Workerより計算に必要な共通で利用するパラメータを取得してS3にアップロード
  2. 別のJob Workerで計算対象とするユーザーを取得し各ユーザー毎のパラメータをSQSに送信
  3. SQSへのEnqueueをイベントとしてLambdaが起動。S3上のパラメータを取得し、ユーザーのパラメータと外部APIへ送信してスコアを取得
  4. DynamoDB等のデータストアへ保存

現在もまだ調整・改善な箇所がありますが、これによりある程度の計算速度を担保できるようになっています。
LambdaからRDSへ接続する際のコネクションプーリング問題があったため、RDSに接続できればどれだけ楽なのだろうと思っていた矢先、AWSさんよりこの問題を解決できる「RDS Proxy」の発表がありました。まだプレビュー版なので、正式リリースされたら真っ先に導入しようと計画しています。

■ 終わりに

現状の検索システムについて紹介させていただきました。
長いこと運用しているシステムではあるのですが、まだまだ足りていない部分が多くあり、今後も事業の成長に合わせてシステムの改善を予定しております。
現在APIチームでは一緒に働く仲間を絶賛募集中です。カジュアル面談も実施しておりますので、ご興味を持って頂けたら是非一度お話しましょう!

--

--

Hiroki Kojima
Eureka Engineering

2014年に株式会社エウレカに新卒として入社。 現在はAPIチームに所属し、Pairsのバックエンド開発を担当。検索周りの機能をメインに担当しています。