Japanese full-text search using Elasticlunr in Zola

Zola の Elasticlunr.js による全文検索を日本で使えるように対応する

hata published on
10 min, 1860 words

Categories: web

続き。 ← /posts/japanese-full-text-search-on-zola/

あらすじ🔗

  • Zola で全文検索を使いたい。
    -> デフォルトだと英語にしか対応していない。
  • 日本語(や中国語)に対応するためには Zola をビルドし直さないといけない。
    -> ローカルで、フラグを変えてビルドに成功。

補足: elasticlunr で日本語を有効にするには日本語の辞書ファイルを取り込まないといけなくて、そうすると Zola のバイナリもすごく大きくなってしまう。 そのため、デフォルトでは日本語検索(と中国語検索)は OFF の状態でビルドされている。 バイナリのサイズ比較は以下のエントリをどうぞ

日本語や中国語を有効化したときの Zola のバイナリの大きさ

最終的に対応したこと🔗

1.elasticlunr において英語以外の場合に必要な追加の javascript🔗

elastilunr のドキュメントを読むと英語以外の言語で使う場合には、追加の JSファイルが必要らしい。

Other languages example in Node.js

Suppose you are using elasticlunr.js in Node.js for other languages, you can download the corresponding language support from lunr-languages, put the files lunr.es.js file and lunr.stemmer.support.js in your project, then in your Node.js module, use elasticlunr.js as:

最終的に以下が必要だった。

  1. lunr.multi.js (要らないかも)
  2. lunr.stemmer.support.js
  3. tinyseg.js
  4. lunr.ja.js
  5. search.js (追記:今回使っている Theme では不要でした)

順にどう手配したかを書く。

1. lunr.multi.js🔗

指定どおり weixsong/lunr-languages から持ってきた。

2. lunr.stemmer.support.js🔗

指定どおり weixsong/lunr-languages から持ってきた。

3. tinyseg.js🔗

指定どおり weixsong/lunr-languages から持ってきた。

4. lunr.ja.js🔗

指定どおり weixsong/lunr-languages から持ってこようとしたら lunr.jp.js はあっても lunr.ja.js がない。

Fork 元の本家リポジトリ MihaiValentin/lunr-languages を覗くと、どうやら カントリーコードである jp (日本国をあらわす)と言語コードである ja (日本語をあらわす)を間違えて lunr.jp.js を当初作った経緯があるらしい。 そこから lunr.ja.js も作られたが、後方互換性のためにちゃんとコード上で対応して両方残されていた。 それらの対応も含めて weixsong/lunr-languages のほうはコードが古くメンテされていないようだ。

とりあえず、さらに Fork して雑に ja 対応をした。 → hatappo/lunr-languages@support-ja-and-trimmer-ja PR も作成したが取り込まれなさそう。

  • ※ 補足: そもそも elasticlunr.js は lunr.js をもとによりシンプル軽量化を目指して作られたっぽい。 なので他言語に対応するためのパッケージを配布する lunr-languages リポジトリも elasticlunr 用のを Fork して用意していたようだ。

5. search.js🔗

Zola 自体のリポジトリの docs/static/search.js にサンプルが置いてあった。ざっくり読んだが一応そのまま使えそう。 検索の仕方や重み付けなどのチューニングはここをいじればできそう。

2.使っている Theme に上記 Javascript を適切に差し込む拡張ポイントが提供されていなかった。🔗

Zola は Tera というテンプレートエンジンを使っている。 使っている DeepThought という Theme では追加の JS を差し込む Tera block が提供されていたが、それを使うと一番最後に読み込まれてしまい都合が悪い(検索結果にスタイルが効かなかった)。 deffer とか使えば解決できたのかもしれないが、よくわからなかったのでこれも Fork して PR を投げた。

https://github.com/RatanShreshtha/DeepThought/pull/44

今見たらマージされていた。ありがとう。 ↓こんな感じで追加の JS を差し込む。 https://github.com/RatanShreshtha/DeepThought#elasticlunr-search-in-other-language

― ※ 補足: ちなみに Zola の作者と Tera の作者は同じ人。

ここまでで、ローカルでは日本語の全文検索が動くようにできた。 リポジトリに Push されたら自動でビルドとデプロイしたく GitHub Actions を使っていたのだけど、ここで2つ問題がある。

  1. 利用してた Zola デプロイ用の GitHub Actions Marketplace Workflow が「日本語検索を有効にした Zola バイナリ」なんて当然使ってくれない。
  2. そもそも上記 Workflow で利用する「日本語検索を有効にした Zola バイナリ」がどこにも UL されていない。

3. 「日本語検索を有効にした Zola バイナリ」を作って GitHub に置く🔗

Zola のリポジトリを Fork して、

--features search/indexing-ja --features search/indexing-zh

の2つのフラグを追加して、ビルドしてリリースしたい。

元のリポジトリは Azure Pipelines を使ってビルドとリリースをしているようだ。

azure-pipelines.yml

Azure は詳しくないし、有料だとまた1つハードルなので、ここは GitHub Actions を使いたいので、書いた。

.github/workflows/release-any-version.yml

GitHub Actions で使うだけなのだけなので Ubuntu 用のバイナリが1つあれば OK なんだけど、せっかくなので Matrix を使って Ubuntu 用と Intel Mac 用のバイナリをクロスビルドするようにしてみた。 しかし、そもそも自分が M1 Mac なので Intel Mac 用のバイナリは動作確認できていない。。(ごめんなさい) じゃあ M1 Mac 用にビルドすればいいんだけど、 GitHub Actions のノードって M1 Mac はまだサポートしてなくないですか?どうすればいいんだろ。

とにかく、バイナリをビルドしリリースすることができた。 最新の 0.14.1 だけ。

Release v0.14.1: Merge pull request #1553 from getzola/next · hatappo/zola

4. GitHub Release に置かれた「日本語検索を有効にした Zola バイナリ」を使ってビルドデプロイする GitHub Actions🔗

が必要なので、これまた Fork した。 上で作ったバイナリを参照するように Dockerfile を書き換えただけ。

https://github.com/hatappo/zola-deploy-action/blob/master/Dockerfile#L17-L18

本当は、使用するバイナリを(デフォルトは残したままで)選択できるように拡張して PR を出したほうがいいのかもしれない。 けど、とりあえずやっつけで。

Zola の elasticlunr で日本語の全文検索を有効化🔗

できた。。

サンプルの GitHub Actions はこんな感じでいいと思います。

on:
  push:
    branches:
      - main

name: deploy
jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:

      - name: checkout
        uses: actions/checkout@v2

      - name: build and deploy
        uses: hatappo/zola-deploy-action@master
        env:
          TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
          BUILD_DIR: .
          PAGES_BRANCH: gh-pages

課題🔗

Zola で defualt_language = "ja" にしただけだと日本語のインデックスは作成されるんだけど英語のインデックスが作成されなくなっちゃって、その結果 rust とか zola とかの英語やローマ字などの用語が全部検索できなくなってしまった。 また対応を考えよう。

続きます。 → /posts/hybrid-ja-en-full-text-search-on-zola/