#198

Public 記事検索を高速化し、インクリメンタルサーチができるようになりました

今回のリリース内容

esaの従来の記事検索エンジン(v1)の様々な問題点を改善した、新しい記事検索エンジン(v2)を使えるようになりました。

なお、今後2ヶ月程度は従来の記事検索エンジン(V1)もお使いいただけます。この移行期間の間にv2で何か問題があった場合には、v1を使う設定に切り替えつつフィードバックをいただけると幸いです。

新しい記事検索エンジン(v2)について

新しく追加された要素

インクリメンタルサーチ

検索欄でクエリを入力すると、インクリメンタルサーチで上位数件の候補が表示され、それらを選択することでその記事を直接開くことが出来ます。また、そのキーワードで何件hitするのか確認できるので便利です。

i-search.gif (332.1 kB)

Best match(Hottest)検索

以下のような要素に基づくスコアによって記事をソートします。

  • WIPよりShipit状態の記事の方がスコアが高い
  • Flowの記事よりStockの記事の方がスコアが高い
    • Flow: カテゴリ部分に日付を含む、もしくは 「#flow」タグがついている記事
    • Stock: カテゴリ部分に日付を含まない、もしくは「#stock」のタグがついている記事
  • アーカイブされた記事のスコアはとても低い
  • 記事の何処に検索クエリがマッチしたか
    • 記事タイトルやカテゴリにマッチしたほうが、記事本文にマッチするよりスコアが高い
  • 直近のStar・Watch・Commentの盛り上がり具合
    • 直近の24時間以内のStarのScoreへの影響度を1とすると、24~48時間以内の場合は0.5、48~72時間以内の場合は0.33、...

改善された要素

  • 速度
    • 記事一覧ページの表示速度
    • 記事検索の速度
    • TOPのカテゴリ内の記事検索の速度
  • 記事一覧・検索結果に対するSortの指定
    • 記事作成順(降順・昇順)
    • 記事更新順(降順・昇順)
    • Star数順
    • Watch数順
    • Comment数順
    • Best match(Hottest)

Webで記事検索エンジンを切り替える方法

esaにログイン後に、記事一覧ページの「 検索エンジン切り替え」からv1とv2を切り替えることができます。

ss 2016-11-19 11.48.35.png (27.0 kB)

APIで記事検索エンジンを切り替える方法

  • GET /v1/teams/:team/posts?q=foo&engine=v2

のように、クエリパラメータで engine=v2 を指定することができます。

また、

  • GET /v1/teams/:team/posts?q=foo&engine=v2&sort=stars&order=desc

のようにすることで、sortとorderを指定することができます。

engine=v2を指定した場合に利用可能なsortとorderのリスト

  • sort
    • updated (default)
      • 記事の更新日時
    • created
      • 記事の作成日時
    • stars
      • 記事へのStarの数
    • watches
      • 記事へのWatchの数
    • comments
      • 記事へのCommentの数
    • best_match
      • 総合的な記事のスコア
  • order
    • desc (default)
      • 降順
    • asc
      • 昇順

v1からv2への移行スケジュール

  • 2016/12/14
    • 新しい記事検索エンジン(v2)がデフォルトになります(Web, API)
  • 2017/01/18
    • 従来の記事検索エンジン(v1)が使用できなくなります(Web, API)

UML

#196: ReleaseNotes/2016/10/22/UML記法に対応しました の機能を使いました ;)

技術的な背景

従来の記事検索エンジン(v1)はesaの開発初期にPostgreSQLとactiverecord-hackery/ransackというgemで作った素朴なものでした。このアプローチではチームの記事数が増えていくにしたがって検索の速度や精度の悪化が顕著になり、スケールしません。

新しい記事検索エンジン(v2)のバックエンドには、Elastic CloudのTokyoリージョンのElasticsearch 5.0を使っています。Elasticsearchはスケーラブルな全文検索エンジンで、検索速度やREST-APIによる設定、柔軟なソート方法の指定なども魅力です。

gemに関してはankane/searchkickelastic/elasticsearch-railsを検討してelasticsearch-railsを採用しました。両方でプロトタイプを作ってみた感想としては、自分でmappingを定義するようならelasticsearch-railsがいいと思います。searchkickはいろいろよしなにやってくれてお手軽なのですが、esaで使う場合にはparent/childなドキュメントに対応しない等の問題がありました。

ユーザーが入力した文字列をElasticsearchのクエリに変換する部分の開発には結構時間を使いました。開発初期は既存のライブラリやそれにパッチをあてたものを使っていましたが、esaの検索のためにカスタマイズする部分が多かったりと無理が出てきたので結局全部書き直しました。

所感

早いもので、RubyKaigi後の9月中旬頃に新しい記事検索エンジンの実装に取り掛かってから約2ヶ月が経ってしまいました。その間Elasticsearchを再入門したり、体調がすぐれない時期があったり、会社が3期目に突入したり色々ありました。ともかく、この新しい記事検索エンジンをリリースできることを本当に嬉しく思います。

今回のリリースは「検索が遅い」「検索精度をもっと良くしてほしい」といった皆様からのフィードバックに背中を押してもらいました。これからも、ご不満やご要望やご感想のフィードバックをお待ちしております。そして今後も検索機能の他にも随時改善を続けていく所存ですので、よろしくお願いいたします。


[ProTip] Webhookでdocs.esa.ioの更新通知を受け取れるようになりました!

Enjoy "(\( ⁰⊖⁰)/)"
https://esa.io

Comments0