Algoliaをご紹介させていただく際に、お客様にデモ的にお見せして、”実装しようと思えば出来るけど、自分でやろうと思ったら面倒ですよね…”と言うような会話をすることが多いのですが、その中の一つが、我々が『Federated Search』と呼んでいる、1つの検索窓から同時に複数のインデックスにクエリを投げて、その両方をイイ感じに画面に表示する、というもの。
例えば、Twitchの場合、下記のようにカテゴリ、ライブ、チャンネル、ビデオにアクセス。
//embedr.flickr.com/assets/client-code.js
Algoliaのドキュメントとしては、 How to Display Results from Multiple Indices with Autocomplete.js ココにまとまっていますので、是非ご覧ください。今回はこれに沿ってやっていきます。
プレーヤーとチームのデータ
今回はNBAのPlayerとTeamをそれぞれ別のインデックスとしてデータ投入します。それぞれのデータはalgoliaのGithubレポジトリ上に置いてあるものを使います
– プレーヤー: https://github.com/algolia/datasets/blob/master/basketball/nba-players.json
– チーム: https://github.com/algolia/datasets/blob/master/basketball/nba-team.json
インデックスの設定
Ruby Clientを使ってやっていきます。
– Players
require 'rubygems' require 'algoliasearch' Algolia.init(application_id:'xx', api_key:'xxx') index = Algolia::Index.new('players') index.set_settings( searchableAttributes: [ 'name', 'team' ], customRanking: [ 'desc(points)' ] )
– Teams
require 'rubygems' require 'algoliasearch' Algolia.init(application_id:'xx', api_key:'xxx') index = Algolia::Index.new('teams') index.set_settings( searchableAttributes: [ 'name', 'location' ], customRanking: [ 'asc(score)' ] )
Index作成後にDashboardで確認。
//embedr.flickr.com/assets/client-code.js
インデックスにデータを投入
先日金沢で仲良くなった加藤さん(@PharaohKJ)がやってるPodcast(Tsundokanai Radio)でEffective Rubyの話を聴いてたら、”あー、俺、よく分かってねーで、イイ感じなノリでRuby書いてきたんだな…”とか思いながら、
//embedr.flickr.com/assets/client-code.js
それっぽく、この2つのインデックスにGithubからダウンロードしてきたデータを投入していきます。
require 'rubygems' require 'algoliasearch' Algolia.init(application_id:'xx', api_key:'xxx') players = Algolia::Index.new('players') teams = Algolia::Index.new('teams') [players, teams].each{|index| batch = JSON.parse(File.read(index.name + ".json")) index.add_objects(batch) }
データが投入できたことを確認。
//embedr.flickr.com/assets/client-code.js
HTML
必要なJavascriptおよびCSSを読み込んで、画面表示用のマークアップ。まんまコピペで。
<html>
<head>
<!-- Include stylesheet -->
<link href="app.css" rel=stylesheet />
</head>
<body>
<!-- HTML Markup -->
<div class="aa-input-container" id="aa-input-container">
<input type="search" id="aa-search-input" class="aa-input-search" placeholder="Search for players or teams..." name="search" autocomplete="off" />
</div>
<!-- Include AlgoliaSearch JS Client and autocomplete.js library -->
https://cdn.jsdelivr.net/algoliasearch/3/algoliasearch.min.js
https://cdn.jsdelivr.net/autocomplete.js/0/autocomplete.min.js
http://app.js
</body>
</html>
JavaScript
Algoliaの実装としてはメインな部分ですが、非常に直感的かな、と。
const client = algoliasearch("xx", "xxx");
const players = client.initIndex('players');
const teams = client.initIndex('teams');
autocomplete('#aa-search-input', {}, [
{
source: autocomplete.sources.hits(players, { hitsPerPage: 3 }),
displayKey: 'name',
templates: {
header: '<div class="aa-suggestions-category">Players</div>',
suggestion({_highlightResult}) {
return `<span>${_highlightResult.name.value}</span><span>${_highlightResult.team.value}</span>`;
}
}
},
{
source: autocomplete.sources.hits(teams, { hitsPerPage: 3 }),
displayKey: 'name',
templates: {
header: '<div class="aa-suggestions-category">Teams</div>',
suggestion({_highlightResult}) {
return `<span>${_highlightResult.name.value}</span><span>${_highlightResult.location.value}</span>`;
}
}
}
]);
CSS
まんまコピペでw
.aa-input-container { display: inline-block; position: relative; } .aa-input-search { width: 300px; padding: 12px 28px 12px 12px; border: 1px solid #e4e4e4; box-sizing: border-box; -webkit-appearance: none; -moz-appearance: none; appearance: none; } .aa-input-search::-webkit-search-decoration, .aa-input-search::-webkit-search-cancel-button, .aa-input-search::-webkit-search-results-button, .aa-input-search::-webkit-search-results-decoration { display: none; } .aa-input-icon { height: 16px; width: 16px; position: absolute; top: 50%; right: 16px; -webkit-transform: translateY(-50%); transform: translateY(-50%); fill: #e4e4e4; pointer-events: none; } .aa-dropdown-menu { background-color: #fff; border: 1px solid rgba(228, 228, 228, 0.6); width: 300px; margin-top: 10px; box-sizing: border-box; } .aa-suggestion { padding: 6px 12px; cursor: pointer; } .aa-suggestions-category { border-bottom: 1px solid rgba(228, 228, 228, 0.6); border-top: 1px solid rgba(228, 228, 228, 0.6); padding: 6px 12px; } .aa-dropdown-menu > div { display: inline-block; width: 100%; vertical-align: top; } .aa-empty { padding: 6px 12px; }
プレーヤーとチームを同時に表示
“r”と一文字入力しただけで↓。直感的なコーディングでサクっといういうUIが構築できるのはとても便利ですね!
//embedr.flickr.com/assets/client-code.js