Search from Scratch
その昔、サイト内検索は鬼門だった。日本語のテキストを巨大な辞書を持つ形態素解析器で正規化し、転置インデックスを構築する。新語が出るたびに辞書をメンテナンスする。検索サーバーを立て、チューニングし、運用する。検索だけで一人分の仕事があった。
このブログに検索をつけた。サーバーはない。静的サイトだ。VitePressで生成したHTMLとJSONだけで動いている。検索もクライアント側で完結させたかった。20年前に夢見たものだ。
英語だけなら当時も今も比較的簡単だ。スペースで単語に分割し、Porter Stemmerで語幹に変換して突合すればいい。runningはrunに、connectedはconnectになる。3KBのnpmパッケージで済む。問題は日本語だった。
日本語はスペースで区切れない。「走った」で検索しても「走る」がヒットしない。形態素解析で単語に分割し、原形に戻す必要がある。MeCabの辞書は50MB超。ブラウザに載せるサイズではない。
OSSで、ブラウザで動く軽量な形態素解析器をC++で書いている。WASMにコンパイルしてgzip後363KB。いまもアクティブに開発中だ。「走った」を渡すと「走る」と「た」に分解して原形を返す。品詞情報も付くので、助詞や助動詞をノイズとして弾ける。こういう使い方のために作っている。自分のブログで試す日が来た。
仕組みは単純だ。ビルド時に全記事を正規化して転置インデックスのJSONを作る。ブラウザ側では検索文を同じロジックで正規化して突合する。1記事あたり1KB前後のインデックス。個人ブログの規模だからフロントエンドで完結する。それでも、20年前を思えば隔世の感がある。
長文の日本語からキーワードを抽出し、正規化し、検索可能にする。サーバーを立てずに。バックエンドエンジニアにとって、この気軽さは格別だ。自己満足だが、小さな夢をひとつ叶えた。