ブログやサービスを作っていると、往々にして検索機能が欲しくなる事があります。
いざ実装しようとするとどの部分に検索をかけるか、部分一致検索にするか完全文字一致にするか…などなど意外とめんどくさい作業ですよね 😅
そんな中、Algoliaは検索に特化したサービスです!
検索機能を自身のサービスに簡単に実装する事が出来ますし、
しかも色んな言語やフレームワークをサポートしています。

Algolia公式ページより引用
フロントであれば今時のReactやVue、バックエンドはRubyにPythonと幅広く対応しています!
実際にどのようなサービスかについては公式の動画があるんですが、
それ以上に公式サイトのWidgetページを見ると、出来る事のイメージがしやすいです。
Widgets Showcase | Vue InstantSearch | Building Search UI | Guide | Algolia Documentation
ここではNuxt.jsにAlgoliaを導入します。
Nuxt ContentというNuxtでブログなどSSGを作るのに特化したライブラリ上での解説ですが、Nuxt.jsで作った場合と差異はないはず。
検証した環境
| 1 | nuxt | 2.14.12 | 
| 2 | @nuxt/content | 1.11.1 | 
前準備
料金について
料金は0円からスタート可能です
 
 ↑の公式のPRICINGページに書かれているように1ヶ月に10,000検索(10UNIT = 10 x 1,000検索)までは無料でいけます。
とりあえず試してみて、検索ボリュームと利便性から費用対効果を考えて判断する、というのでも良さそうです。
アカウント登録
アカウント登録はこのようなサービスなのでGitHubも選択出来るのは嬉しいところ!
 
 名前や会社の情報を入力して作成、特に迷うところはなし。
またアカウント作成時にクレジットカードの登録は不要です。
気付いたら支払わないといけない、、といった心配をしなくて済むので安心ですね 😊
Algoliaの設定
まずAlgoliaで大きく3つの設定をします。
- indexの作成(検索対象1つにつき、1つのindexを作成)
- 検索するための元となるデータを設定
- 検索対象のリストを作成(重み付けも合わせて)
1. indexの作成
検索する対象に対して1つのindexを作成します。
To handle indices across multiple environments, just prefix/suffix your index name like dev_NAME, test_NAME, or prod_NAME
複数の環境でインデックスを処理するには、dev_NAME、test_NAME、prod_NAMEなどのインデックス名のプレフィックス/サフィックスを付けるだけです(Google翻訳)
 
 と作成時に表示されるので、
- dev_・- prod_のようにprefix/suffixをつければ自動的に開発用、本番用といった差異を自動判別してくれる
- 開発用、本番用など環境毎に違うデータを試したい場合は違うindexを作る必要がある
という事が分かります。
2. 検索するための元となるデータを設定
検索するためのデータを追加します。
追加方法は
- API経由でAlgoliaにアップロード
- JSONファイルをローカルで作成してAlgoliaにアップロード
- Algolia上で入力
の3つ。
私の場合ブログのため、
masterマージされたのをフック → CIでAPIを叩いて検索用のJSONをAlgoliaに自動アップロード
というのが最終目標ですが、今は簡単に検索を試したいので検索用のファイルをアップロードします。
[
  {
    "title": "reset.cssをNuxt.jsに導入する",
    "body": "reset.cssをNuxt.jsのプロジェクトに導入する方法を書きます",
    "tags": ["Nuxt.js", "reset.css"]
  },
  {
    "title": "Nuxt.jsで必要なFont Awesomeだけをimportする",
    "body": "Nuxt.jsでFont Awesomeを使用する際に使われる nuxt-fontawesome パッケージ。",
    "tags": ["Nuxt.js"]
  },
  {
    "title": "VueでのCSS Modulesの書き方",
    "body": ""
  },
  {
    "title": "Reset.cssをNext.jsに導入する",
    "body": "Reset.cssをNext.jsに導入します、ここでは2つのやり方をご紹介します。",
    "tags": ["Next.js", "reset.css"]
  }
]自分のブログの記事データをいくつか適当に、そこに対してタグを設定した状態で上げてみました。
なおここでのアップロードはJSON以外にも、CSV, TSVが対応しています。
 
 3. 検索対象のリストを作成(重み付けも合わせて)
検索対象とする属性を設定します。
また、どの属性を優先的に検索対象とするかを設定します。
 
 例えば↑の画像の場合、
body を検索対象から外し、優先度はtagsの方がtitleよりも高い、という設定になります。
Nuxt.jsへの実装
公式にVueを実装するやり方があるためそちらを参考にします
https://www.algolia.com/doc/guides/building-search-ui/getting-started/vue/
必要な値を取得する
必要な値は3つ。
- index名
- Application ID
- Search-Only API Key
index名は、Algolia作成時に付けたもの。
Application IDとSearch-Only API KeyはAogoriaのAPI Keysページに載っています。
 
 これらの値は実装時に使用します。
ライブラリのインストールとNuxtの設定
検索に必要なのはalgoliasearch。
UIを簡単に実装するのにvue-instantsearchとinstantsearch.cssの2つを使います。
$ yarn add vue-instantsearch algoliasearch instantsearch.csspluginsの作成
Vue.use()を使う必要があるためpluginsを使います。
私のプロジェクトではTypeScriptを使っているので.tsで作成、またvue-instantsearchがTypeScript未対応のため、ひとまず@ts-ignoreで回避。
import Vue from 'vue'
// @ts-ignore
import InstantSearch from 'vue-instantsearch'
 
Vue.use(InstantSearch)作成したプラグインをnuxt.config.jsで設定。
mode: 'client' を使用しないとエラーが起きてしまうので設定しています。
export default {
  plugins: [{ src: '~/plugins/Algolia.ts', mode: 'client' }],
}コンポーネントを作成
検索をするためのコンポーネントを作ります。
ここで先ほどの index名・Application ID・Search-Only API Keyを使用します。
<template>
  <ais-instant-search :search-client="searchClient" index-name="<index名>">
    <ais-search-box />
    <ais-hits>
      <div slot="item" slot-scope="{ item }">
        <div>{{ item }}</div>
      </div>
    </ais-hits>
  </ais-instant-search>
</template>
 
<script>
import algoliasearch from 'algoliasearch/lite'
import 'instantsearch.css/themes/algolia-min.css'
 
export default {
  data() {
    return {
      searchClient: algoliasearch('<Application ID>', '<Search-Only API Key>'),
    }
  },
}
</script>そして上記コンポーネントを使用するページでimportして呼び出します
<template>
  <div>
    <search />
    ・・・
  </div>
</template>
 
<script>
import Search from '~/components/organisms/search/index.vue'
 
export default {
  components: { Search }
  ・・・
}
</script> 
 検索が出来るようになりました!
ハイライト表示する
検索結果は以下のコードの部分です
<ais-hits>
  <div slot="item" slot-scope="{ item }">
    <div>{{ item }}</div>
  </div>
</ais-hits>item は検索結果の1つになります。
 
 ↑は「nux」というワードで調べた時の結果。
_highlightResult.title.valueなどに検索結果があるのが分かります。
そのため、先ほどのコードを以下のように書き換えてみると
<template>
  <ais-instant-search :search-client="searchClient" index-name="TECH-BROCCOLI">
    <ais-search-box />
    <ais-hits>
      <div slot="item" slot-scope="{ item }">
        <div v-html="item._highlightResult.title.value" />
        <div v-html="item._highlightResult.body.value" />
      </div>
    </ais-hits>
  </ais-instant-search>
</template>検索結果にハイライトしながら表示出来るようになりました!
 
 課題
Nuxt.jsで実装時の課題としてCSR/SSRのDOMの違いに関するwarningメッセージがコンソールに表示されます。
 
 プラグインでUI実装のためのvue-instantsearchを使ったのが良くなかったかな… 🤔
今回はAlgoliaの検索が出来る事を簡単に確認したかったので、
vue-instantsearchとinstantsearch.cssを使いましたが、
次はこれらを使わずに実装してみたいと思います!
 
  
  
  
  
  
  
 