モノラルログ

マツオ ( @matsuoshi / monaural.net ) のざっくりしたブログです

algolia でサイト内検索、オートコンプリートを実装する

f:id:matsuoshi:20200613101549p:plain

無料から使える爆速の全文検索サービス Algolia

www.algolia.com

別でやってる音楽ブログ "pause" のほうに導入してみました。(右上のメニューから検索できます)

pause.monaural.net

こちらブログは hugo + netlify でホスティングしているんですが、静的サイトジェネレータで作ったサイトにも簡単に全文検索を仕込めますね、便利……!

オートコンプリートを実装する

さて、Algolia の使い方。

バックエンド側、 indexデータ の登録方法なんかはググるとすぐ出てきます。一方フロントエンド側、オートコンプリートの実装方法についてはちょっと試行錯誤したので、メモを残しておこうかと。

InstantSearch.js を使う

具体的には、Algolia から提供されている InstantSearch.js を使います。ドキュメントはこちら

www.algolia.com

必要なパッケージとしては、algoliasearch と instantsearch.js の2つです。インストールしておきます。

npm install algoliasearch instantsearch.js

JavaScript を書く

ざっくりこんな感じ

import algoliasearch from 'algoliasearch/lite'
import instantsearch from 'instantsearch.js/es'
import {connectAutocomplete} from 'instantsearch.js/es/connectors'

// initialize
const search = instantsearch({
  indexName: 'algoliaのインデックス名',
  searchClient: algoliasearch('アプリID', 'APIキー')
})

// Helper for the render function
const renderIndexListItem = ({indexId, hits}) => `
  ${hits
  .map(
    hit =>
      `<li><a href="${hit.permalink}">${hit.title}</a></li>`
  )
  .join('')}
`

// Create the render function
const renderAutocomplete = (renderOptions, isFirstRender) => {
  const {indices, currentRefinement, refine, widgetParams} = renderOptions
  const $input = widgetParams.container.querySelector('#autocomplete_input')
  const $result = widgetParams.container.querySelector('#autocomplete_result')

  if (isFirstRender) {
    $input.addEventListener('input', event => {
      refine(event.currentTarget.value)
    })
  }
  $input.value = currentRefinement

  result.innerHTML = indices
    .map(renderIndexListItem)
    .join('')
}

// Create the custom widget
const customAutocomplete = connectAutocomplete(renderAutocomplete)

// Instantiate the custom widget
search.addWidgets([
  customAutocomplete({
    container: document.querySelector('#autocomplete')
  })
])

search.start()

algolia search のAPIキーなどは、管理画面から取得必要です。

この例だと renderIndexListItem() が、検索結果をレンダリングする部分になります。

html側の準備

オートコンプリートを入れたい部分に、こんな感じの html を追記

<div id="autocomplete">
  <input id="autocomplete_input">
  <ul id="autocomplete_result">
</div>

id名とかはてきとうにJS側と揃えておけばよし

以上で検索処理の実装は完了です、テキストフィールドに文字を入力することで、リアルタイムなオートコンプリートが行われると思います。

あとはいい感じにCSSで見た目を調整ですね


実装例

こちらのブログになります (右上のメニューから)

pause.monaural.net

追加でメニューの開閉処理とか、初期状態で検索を実施しないようにするとか、入力値が空の場合は検索結果を表示しないとか、こちょこちょコードを足して調整しています。