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

