Elasticsearch Top Hits Aggregationの活用とデモ
脱単なる一覧表示!俯瞰できる検索結果を利用者へ提供することで、効率のよい情報収集と今まで知らなかった情報を気づかせる。
もしかしたら、クエリー関連の記事を書くのははじめてかも。基本は飛ばして、いきなりAggregationです。そのうち基本も書きます。
Aggregationと言うとファセット検索で使用したり、集計したりどちらかと言うと分析関連で使われることが多そうな気がしますが、今回はいわゆるブログや企業サイト等で利用されているサイト内検索をAggregationを使ってもっと便利にしたいと思います。それと query DSLの説明も。
と言うわけでいきなりデモです。
デモアプリのあまりの殺風景さに戸惑わないでください。。例えば「日本語で全文検索」などElasticsearchに関連する質問を入力すると検索結果が表示されます。このデモアプリでは Elasticsearch 関連のブログなど4サイトをインデックスしてあります。
画面左側がAggregationを使って表示している検索結果です。ドメイン名を基準にグルーピングして、各サイトのベストヒットを2件ずつ表示しています。また、各サイトの表示順位もランクの高かった検索結果ページを基準に上位3サイトを掲載していますので、キーワードがかわればページの順位だけでなくサイトの順位もかわってきます。
どうだろうか?
検索結果を俯瞰的に閲覧でき、かつ右側に表示されている一覧に無いページも掲載されていたりします。企業サイトであれば、製品情報やリリース情報、よくある質問などコンテンツの種類で俯瞰できると情報を見つけ易いのではないでしょうか。
もちろんウェブサイトの情報だけでなく、コマースサイトの商品検索などでも応用できます。
技術的な話しに戻ると、この検索結果ページはElasticsearchへ1度の検索リクエストで返却された情報をほぼそのまま表示しているだけで実現しています。
実際に使用しているHTMLテンプレートはこちら
実際に使用しているquery DSLはこちら
大まかには、基本的なクエリーに”aggs”と言うJSONパラメータでAggregationの設定を追加しています。
{
"query": {...}, # 検索条件
"size": ..., # 画面右側の一覧表示最大数
"_source": {...}, # 画面右側の表示フィールド
"higlight": {...}, # 画面右側のハイライト表示フィール
"aggs": {...}, # 画面左側のAggregationのクエリー
}
aggsの内容をもう少し詳しく説明すると、
まずはグループの設定です。aggs.top_sites.terms では主にグルーピングする条件を設定しています。ちなみに top_sites と言う名前は任意の名前が付けられます。
# グルーピングするフィールド
aggs.top_sites.terms.field# グループのソート条件
aggs.top_sites.terms.order# グループを表示する最大サイズ
aggs.top_sites.terms.size
field には、ドメイン名がストアされている url.domain フィールドを設定して、サイト毎にグルーピングされるように設定しています。
注意:グルーピングされる単位は、指定したフィールドデータの言語処理された後のデータが使用されます。そのため、not_analyzed で設定されているフィールドを使用した方が、意図した単位でグルーピングされると思います。
order では、aggs.top_sites.aggs.top_hit に定義ししている、各サイトの検索結果ページの最大スコアを使用して、グループがソートされるように設定しています。
次に、各サイト毎(グループ毎)に表示している検索結果ページについての設定です。先ほどのグループの設定をしたaggsに入れ子にして検索結果ページ用のaggsを設定しています。※ top_site_hits は任意の名前です。
# 表示に使用するフィールド
aggs.top_sites.aggs.top_site_hits.top_hits._source# ハイライトの設定
aggs.top_sites.aggs.top_site_hits.top_hits.highlight# 一覧に表示する最大数
aggs.top_sites.aggs.top_site_hits.top_hits.size# グループのソートで使用するスクリプトフィールド
aggs.top_sites.aggs.top_hit
ハイライトやサイズなども細かく制御できます。その他ソート条件等も設定できます。このデモアプリでは、ソート条件は設定していないので、メインのクエリーのスコア順でソートされます。
ちなみに、aggs.top_sites.aggs.top_hitで設定しているスクリプトでは、lang を指定しないと、デフォルトでmvel が使用されるようでエラーになってしまいました(v 1.3.1)。
※ Elasticsearch の script.disable_dynamic: がデフォルトのsandboxなので、mvelは使用できない設定)明示的に groovy を設定するとちゃんと動きました。新しいElasticsearchのバージョンなら指定しなくても大丈夫かも?未確認。
まとめ
クエリーは少々複雑ですが、フロントエンドの開発は検索結果をそのまま表示するだけですので非常に簡単です。さらにアクションが少ないため、レスポンシブにしておけばPCでも、スマフォでもタブレットでも機能を減らさずにそのまま使えてしまいます(デモアプリも一応レスポンシブ!)。また、メインの検索結果のsizeを0(ゼロ)にして、Aggregationの結果だけを使用してとにかく俯瞰していろいろ見せたいと言うのも使い易い検索アプリが作れそうです。