オンラインドキュメントと日本語全文検索

自社では Sphinx というドキュメントツールを利用しているのですが、残念ながらこれに付属している検索機能の日本語検索はかなり厳しいです。また残念ながら Sphinx 開発側も検索周りを改善するという予定は直近ではないようです。

そして検索というのはとても難しい技術なため自分のような素人では導入して「普通に期待する動作」をさせるまでの距離はとても遠いです。

ただ、なんとかして日本語全文検索を実現したいという思いはここ10 年くらいずっと思っていました。これは自社の Sphinx テーマを作ってくれている社員ともよく話をしていたのですが、どうしてもリソースをつぎ込めずにいました。

まとめ

  • ドキュメントスクレイパーの実行は GItHub Actions (Self-hosted Runner) を採用した
  • 自社 Sphinx テーマの検索バーへ組み込む

ドキュメントの重要性

力を入れているドキュメントで検索がいけてないというのは本当に歯がゆい状態でした。実際顧客から検索が使い物にならないというお問い合わせを頂いたこともありました。

Algolia を検討

さらにオンラインドキュメント検索ツールは OSS 限定のため商用製品では利用できません。

Meilisearch を検討

Meilisearch はパリのスタートアップ?が開発している Rust で書かれた検索エンジンです。動かすまでが本当に簡単でバイナリダウンロードしてきてすぐに動かせます。

また docs-scraper という HTML ドキュメントを解析して検索インデックスを作成してくれるツールが Python で用意されていました。(もともとこれは Algolia が公開していたモノをベースに作ったようです)

ドキュメントもしっかりと書かれており一通り読み込んで見た限り、どうやら自分がやりたいことが実現しているということがわかりました。

Meilisearch を検証

Meilisearch は v0.27.0 にて日本語に対応しています。これを実現しているのは Lindera という kuromoji-rs のフォーク実装です。

実際に docs-scraper で自社製品ドキュメントを読み取ったら問題なく日本語が検索できました。

Meilisearch を採用

また結局 docs-scraper を定期実行する必要があるため、自前で構築する方針をとりました。

構成はシンプルです Cloudflare DNS Proxy + Nginx + Meilisearch だけです。

サーバーは CPU バウンドになることを考えて Linode専有インスタンス 2C/4G を採用しました。費用は月 $30 です。

実際に複数のドキュメントのインデックスを追加してみたところ特に問題なく処理できていました。

docs-scraper 実行には GitHub Actions (Self-hosted runner) を採用

頻繁にインデックスを更新したいと考えていたのと、Meilisearch の近くで docs-scraper を実行したいと考えていたので今回は GitHub Actions (Self-hosted runner) を採用しました。

Self-hosted runner は自分の用意したサーバーで GitHub Actions を実行する仕組みです。以前に触ってみてとても簡単に構築することができるのを覚えていたので、今回試してみました。

実際ためしたらより構築が簡単になっていてびっくりしました。

構築して GitHub 側に Self-hosted runner が認識されてしまえば、あとは普通に GitHub Actions の YAML を書くだけです。

on:
push:
paths-ignore:
- '**.md'
branches: [ "main" ]
pull_request:
branches: [ "main" ]
workflow_dispatch:schedule:
# JST は 2:00 は UTC の 17:00
# 1-5 で 月曜日から金曜日
- cron: '0 17 * * 1-5'
jobs:
docs-scraper:
runs-on: [self-hosted, linux, x64]
strategy:
max-parallel: 1
matrix:
config: [sample1.json, sample2.json]
steps:
- uses: actions/checkout@v3
- name: Run scraper
env:
HOST_URL: ${{ secrets.MEILISEARCH_HOST_URL }}
API_KEY: ${{ secrets.MEILISEARCH_API_KEY }}
CONFIG_FILE_PATH: ${{ github.workspace }}/${{ matrix.config }}
run: |
docker run -t --rm \
--network host \
-e MEILISEARCH_HOST_URL=$HOST_URL \
-e MEILISEARCH_API_KEY=$API_KEY \
-v $CONFIG_FILE_PATH:/docs-scraper/config.json \
getmeili/docs-scraper:latest pipenv run ./docs_scraper config.json

docker run して終わりです。あとは好きなだけドキュメントを登録します。これでドキュメントをスクレイピングしてインデックスを張るところまでは用意できました。

ちなみに誰も使って居なさそうな丑三つ時にスクレイピングを実行しています。

Self-hosted な GitHub Actions 経由で doc-scraper が動いてる

動作

docs-scarper でインデックスを作成し docs-searchbar.js で検索している様子

Sphinx テーマに docs-searchbar.js を組み込む

組み込むべき JavaScript はたったこれだけです。

import docsSearchBar from 'docs-searchbar.js'

docsSearchBar({
hostUrl: 'https://meilisearch.example.com/',
apiKey: 'xxx',
indexUid: 'doc',
inputSelector: '#search-bar-input',
})

カスタマイズもいろいろ出来るようなので、テーマに合う感じでデザインを変更し、使いやすく組み込みました。

利用するには Sphinx の conf.py にて以下を設定するだけで利用可能です。

html_theme_options = {
'meilisearch': True,
'meilisearch_api_key': 'xxx',
'meilisearch_host_url': 'https://meilisearch.example.com/',
'meilisearch_index_uid': 'doc'
}
Sphinx テーマ + Meilisearch docs-searchbar.js over HTTP/3

タイポ耐性

ライセンスをライスンスと打ち間違えてみた

雑感

費用も 月 $ 30 だけですし検索対象のドキュメントは好きなだけ増やせます。Meilisearch の検証、構築で 3 日、Sphinx 組み込みで 2 日程度で実現出来そうなのでコスパも不満なしです。

ねんがんのオンラインドキュメントツールでの日本語検索が実現できて大変満足しています。

--

--

Erlang/OTP / 時雨堂 / WebRTC / E2EE / WebTransport

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store