やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

Elasticlunr.jsで全文検索してみた(日本語)

 できたっぽい。

情報源

手順

git clone https://github.com/t-kuni/elasticlunr-sample.git
cd elasticlunr-sample
npm install
node index.js

コードをみてみる

 本文を登録する。

index.addDoc({"id": 1, "body": "カメラ 犬"});
index.addDoc({"id": 2, "body": "本棚 猫"});
index.addDoc({"id": 3, "body": "水 刺身"});

 検索する。キーワードは

const r = index.search("本", {
    fields: {
        body: {boost: 1},
    },
    expand: true,
});
console.log(r);

 実行結果。

$ node index.js
[ { ref: '2', score: 0.060858424387715646 } ]

 id=2がヒットした。

サイトに組み込みたい

 これを静的サイトジェネレータなど自前のサイトに組み込みたい。

 問題があることに気づく。どうやって本文を追加するの? コード例は文字リテラルで本文かいてあるけど、本番では別ファイルにあるはず。

本文を追加する

 ふつうサイトの本文はHTMLである。だがこれには多数のタグが入っている。そのまま本文として登録するわけにはいかない。Markdownも同じだ。メタ文字がある。

  • HTML
  • Markdown
  • document.body.textContent
  • document.body.innerText

 document.body.textContentを追加すればいいのかな? 最終的にHTMLで描画されるときのテキスト内容のみを抽出できると思われる。それともdocument.body.innerTextだろうか? まあそのあたりだろう。たぶん。

全ファイルを取得する

   本文ファイルをすべて登録したい。どうすればいい?

 JSのServiceWorkerを登録するときのアレが使えるかもしれない。

 あるいは静的サイトジェネレータならふつうにファイルアクセスすればいい。ただ、それをJSコードにするにはどうすればいい? Node.jsならローカルファイルにアクセスできるAPIとかがあるのかな?

fs, glob

 Node.js限定であるっぽい。

npm i -D fs glob
const glob = require('glob');
glob(path, (err, files) => {
    return files;
});

 しかし以下エラーに阻まれる。

Module not found: Error: Can't resolve 'path' in 

 ググってみるも何を言っているのかさっぱりわからず。

 たぶんWebとNodeの文脈が別なんだろう。そこをよしなにやってほしいのだが。

 結局、WEBにおいてあるディレクトリ配下のファイル一覧取得する手段はないってことかな。

 JSで動的にパス一覧をつくることはできないと。Node.jsでならできるけど、Web上ではムリってことかな。それじゃ困る。

bash

 bashならすぐにできる。

find . -type f

 カレントディレクトリ配下にある全ファイルを取得する。

./content-0.md
./content-0.html
./content-0.txt
  1. この一覧をWebにUPする
  2. JSでこの一覧.txtを読み込む
  3. elasticlunrのindex.addDocにぶちこむ

 一覧.txtは性的ジェネレータのようにローカルで生成せねばならない。

 さらに一覧.txtを読み込んでelasticlunrのindex.addDocにぶちこむコードを書かねばならない。面倒だが、これが一番できそう。

所感

 めっちゃ大変そう。JSは外部ファイルと連携しようとすると、一気に難しくなる。

対象環境

$ uname -a
Linux raspberrypi 5.4.83-v7l+ #1379 SMP Mon Dec 14 13:11:54 GMT 2020 armv7l GNU/Linux