Next.jsで作ってみたブログに検索機能を導入する
TL;DR
検索機能がやっぱり欲しかったので、とりあえず形態素解析とflexsearchを使って実装してみた。やっぱり感度がなんかなあ、という感じなので、ngramとかを併用したほうがいいかもしれない。
基本戦略
完全AMP対応させたいので、getServerSideProps内でqueryを受け取って、flexsearchにかける。検索対象は、サーバーに上げる前にdata.jsみたいな感じでキャッシュしておいて、そこを参照する。
formはこんな感じで作成して、getでsearchページに/search?q=wordみたいな感じで飛ばす。
ampのときにformで必要になってくるのは、target部分で_topか_blankを指定する必要があり、_topだとそのまま、_blankだと新しいタブで開くらしい。
形態素解析
kuromojinを使った。まずはblog postを全部とってきて、markdownをtextに変換した後形態素解析して、それをcache/data.jsのような形で保存する。markdown -> textにはstrip-markdownを利用した。
形態素解析した結果はregexに関わりそうな部分を抜いて(highlight機能とかのときに邪魔かなと思った)、検索に使用しそうな名詞、動詞、形容詞を残した。また、単語長は2以上のものだけにした。このへんは設定詰めたほうが良さそう。今回はタイトルと本体部分だけを検索するようにしているが、そのへんは足すだけなので足せばいいと思う。
大まかな流れは、getAllPostsPathで全体をとってきて、中身をgray-matterでよんで、filterTockenでほしいトークンだけとってきて、とってきたトークンを全部wordとして保存しているだけ。
makeCache.js
pre-commit
毎回これを実行するなんて間違いなく忘れるので、huskyというパッケージを使った。
package.jsonのbuildとかの部分を以下のように変更する。
package.json
こうすると、commitするたびに自動でmakeCache.jsが走るので楽。
huskyで設定したpre-commitの動作を走らせたくないときは、
でスルー出来る。
search page
ということでsearch pageを作っていく。getServerSidePropsはctx変数をうけとる。ctxには大体の情報が入っている。今回はquery結果だけほしいのでctx.queryだけ使う。
wordsはmakeCache.js時点でスペース区切りで保存してあるので、flexsearchのtokenizeはカスタムしたもの(空白区切りでarrayにするだけ)を使う。それ以外はflexsearchのドキュメントに書いてあるとおりだと思う。idがurl用のパスになっているので、そのまま渡している。
ということで、とりあえずこんな形でサイト内の記事検索を実装してみた。Googleはすごい。