フリーキーズ | 独学プログラミング

日本語全文検索を導入したいのでFessに入門してNext.jsで使ってみた

最終更新日
【画像】日本語全文検索を導入したいのでFessに入門してNext.jsで使ってみた

日本語による全文検索を導入したいという気持ちで調べたところ、AlgoliaやElasticsearch、Supabaseなど、多くのソフトウェアが出てきました。
少し前であれば、自前でMySQLを用意してMroongaあたりをインストールしていましたが、現在では大きく進歩しています。しばらく全文検索を実装する機会がなかったのでワクワクです。

はじめはElasticsearchを導入しようとしました。しかし、いくらか触ったところ「高機能だが学習コスト高め」という結論に至りました。(導入自体はDockerで簡単になっていました)
そこで、「簡単に構築できる全文検索環境」のキャッチコピーに惹かれ、Fessへ入門することに決めたので備忘録を残します。

Fessとは

株式会社コードリブズという企業が提供するオープンソースの全文検索サーバーです。
とにかく簡単に導入でき、それなのに高機能な全文検索システムです。裏側はElasticsearchかOpenSearchで選べるようになっています。

Fessのインストール

早速、Fessをインストールしていきます。基本的に下記リンクの公式ドキュメントに沿って進めていくので、どちらかと言うと公式ドキュメントをご覧になることをおすすめします。
今回はmacOS+Docker環境で最低限使える環境を作っていきます。

Docker版はGitHubリポジトリにあるDocker Composeのyamlファイルを使います。
git cloneしてみましょう。

git clone git@github.com:codelibs/docker-fess.git fess
cd fess/compose
docker compose -f compose.yaml -f compose-opensearch2.yaml up -d

たったこれだけで完了です。

起動動作確認

ブラウザでhttp://localhost:8080にアクセスしてみましょう。
下の画像のような画面が出てきます。

Fessログイン画面

Fessログイン画面

次に右上のLoginからログインします。デフォルトでユーザー名とパスワードはadminですが、すぐにパスワードを変更できます。
パスワード変更が済んだら、右上のメニューからAdministrationをクリックして管理画面に入りましょう。下のスクリーンショットのような管理画面が表示されます。

Fess管理画面

Fess管理画面

起動が確認できたら、次のステップとして実際にインデックスを作成してみます。

インデックスの作成

今回はFessのWebクローリング機能を使っていきます。(とても便利)
ただ、注意点として自社や自身が保有するWebサイトを対象にしてください。他社のWebサイトに余計な不可を加えることは避けましょう。

以下の画面から対象のURLを設定します。

クローラー設定

クローラー設定

作成したら、"Scheduler"メニューから"Default Crawler"をクリックし、"Start now"で開始しましょう。
下のスクリーンショットのように、"Crawling Info"でクローラーのステータスを見ることができます。(スクリーンショットは完了後)

スケジューラー設定

スケジューラー設定

Fessクローラー実行

Fessクローラー実行

クローラー情報

クローラー情報

検索動作確認

次に検索できるかを確認しましょう。
右上にあるツールバーの"Search View"、またはサイドバー上部にある検索窓からクローリングしたWebサイトに掲載されていそうな語句を検索してみます。

Fess検索窓

Fess検索窓

検索結果にスコア(検索語句と対象の近似性)付きで検索結果が表示されます。これで検索が動作していることがわかりました。

Fess検索結果

Fess検索結果

Next.jsから使ってみる

「GUI上で検索結果が見られる=APIで利用できる」状態なので、Next.jsから使ってみましょう。
まずはAPIの確認です。公式ドキュメントではこちらに詳しく書かれています。

API動作確認

先ほど、"Python"を検索語句とした結果を画面上で表示しました。同じようにAPIで叩いてみます。
検索APIはapi/v1/documents?q={検索語句}なので、以下のコマンドを叩きます。

curl -X GET 'localhost:8080/api/v1/documents?q=Python' | jq .

下記画像のように、良い雰囲気で取得できています。

Fess APIテスト

Fess APIテスト

Next.jsにコンポーネントを作る

Next.jsで上記APIを使うために、検索フォーム用コンポーネントを作成します。
なお、前提としてAPIへリクエストするため、Next.jsの設定はSSRであるとします。また、今回は簡略化のためにMantine UIを利用しています。

import { useState } from 'react'
import { useForm } from '@mantine/form'
import { Box, Button, TextInput } from '@mantine/core'

export function Search() {
  const [items, setItems] = useState([])

  const form = useForm({
    initialValues: {
      query: '',
    }
  })

  const fessSearch = async () => {
    const res = await fetch(`/api/fess?q=${form.values.query}`)
    const data = await res.json()
    setItems(data.items)
  }

  return (
    <Box>
      <form onSubmit={form.onSubmit(() => fessSearch())}>
        <TextInput
          label="キーワード"
          placeholder="キーワード"
          {...form.getInputProps('query')}
        />
        <Button type="submit">検索</Button>
      </form>
      {items.length > 0 && (
        <p>検索結果</p>
        <ul>
          {items.map((item: Item) => (
            <li key={item.url}>
              <a href={item.url}>{item.title}</a>
            </li>
          ))}
        </ul>
      )}
    </Box>
  )
}

最終的に/api/fessへリクエストします。
/api/fessの内容は以下です。Next.js 13系で使えるApp Routerの場合だと実装が変わるので、それぞれ記載します。

若干デザインはいじっていますが、以下のように検索結果が表示されれば完了です。

Fess + Next.js通信

Fess + Next.js通信

簡単に導入できるFessでお手軽全文検索

今回は最短距離で試していきましたが、実際に本番運用する際はAPI Keyの発行やインデックス作成のワークフローを考慮する必要があります。
そういった点を念頭に置いても、Fessは非常に簡潔な導入方法で利用できるためおすすめです。

よりビジネスシーンに活用したい場合は、以下のプランもあります。

他の全文検索サービスと比べても安価なので、「全文検索だけ導入したい」というユースケースでぜひ活用していきましょう。

関連するコンテンツ