| @技術/プログラミング

ブログ過去記事の閲覧 UI にはこだわりがある。これまで何度か記事を書いた。

このブログの維持管理で一番時間を割いているのが Archives ページだ。しかしアクセスログを見ると自分以外はほとんど利用していない。完全に自己満なのだが、過去の自分を振り返ることができてとても自分には有意義なページだ。

過去記事を振り返るときには検索をしたくなる。タイトルのみであればページ内検索で探せるが、やっぱり本文込みで検索したい。 Lokka の検索はあるが、検索結果ページは 7 件ずつ(この値はカスタマイズできる)表示で全文表示される。自分は検索キーワードに関する記事が存在するか知りたい訳ではない。著者なのでキーワードに関連する記事があるかないかくらいわかってる。じゃなくて過去の自分がいつ頃どの密度でそのトピックについて書いていたかを知りたいのだ。

タグやカテゴリーで絞り込む手もある。しかしカテゴリーやタグは理想的な分類ではない。二つのカテゴリーを横断するような記事があるし、タグは設定し忘れていることが多い。全文検索が一番頼りになる。

SQL で全文検索的なことをやろうとするとパフォーマンスが良くないだろう。やっぱり全文検索システムが欲しい。

Tantivy と Tantiny

とはいえ、個人のブログで全文検索エンジンを導入するのはしんどい。確かに Apache Solr や Elasticsearch を個人ブログに入れるのはきつい。もっと手軽に使えるものはないか探していて、 Rust 製の全文検索システム Tantivy と、その Ruby クライアントの Tantiny を発見した。

これがめっちゃ簡単で昨日数時間サンデープログラミングをして導入できた。システム環境に適合するビルド済みのバイナリが GitHub にあれば Rust 環境のセットアップすら必要ない。 Gemfile に gem 'tantiny' と書いて bundle install するだけで使えてしまう。

うまくいかなかったもの

最初、同じ Rust 製で Wasm までセットで提供してくれる tinysearch を試した。 JSON 形式で全ファイルを書き出すだけで使えるやつだ。しかし残念なことに日本語では全く使えなかった。自然言語処理をやろうとしていてあるあるのパターンだ。日本語は MeCab などでトークナイズしてやる必要がある。

デフォルトのトークナイザーでもそこそこに優秀な Tantivy

Tantivy にもトークナイザーをカスタマイズできる仕組みはあるが、標準の Simple Tokenizer でもそこそこ精度が高い。固有名詞にちょっと弱いが、辞書ファイルがないので仕方ないだろう。

個人ブログでも全文検索できる時代

このブログは個人ブログだが、画像のリアルタイムリサイズサーバーを動かしている(おかげで S3 の転送量が安くて済んでいる)し、 TF-IDF で関連の高い記事も表示している。それに加えて全文検索まで入れてしまった。こういうのは大手のブログサービスを利用しないと使えない機能だったが、 OSS と新しいプログラミング言語( Go や Rust )のおかげで個人でもそこそこのスペックのサーバーでこれらを利用することができるようになってきた。 MovableType でサイトを構築していた時代から何も進歩していないようで実はとても進歩している。こういう文化の灯火が消えないようにしていきたい。

| @技術/プログラミング

松浦福島初崎海岸のドクロのような岩
松浦福島初崎海岸のドクロのような岩

Mac の Homebrew のライブラリ群を久しぶりにアップデートした。 tmux と fish のバージョンを上げたら tmux が動かなくなってめっちゃ焦った。いろんなものを同時にバージョンアップするとどっちに原因があるのかわからなくて困る。結局、 brew reinstall tmux で事なきを得た。

次に VPS の Ubuntu のバージョンが古くなっていたのでアップグレードした。ついでにいろいろ気になってたところ(ログローテートがうまく動いていないところとか Nginx の設定ファイルの配置など)を直して回った。

OS のアップグレードに伴って Ruby の再インストールが必要になり、 Ruby 再インストール後にアプリケーションを deploy しようとすると mimemagic gem が yank されていたりでライブラリのアップデートが必要になった( MimeMagic は脆弱性があって Mercel に変更しないといけなかったが、変え忘れていたところがあった)。これによって引きずられるように gem のアップデートが必要になり、うっかり capistrano3-puma を v5 系にしたところ、 puma の起動ができなくて困った。どうも puma の v5 ではデーモン化オプションが削除されているようで、 capistrano で puma を再起動させたりはできないようだった。いろいろ面倒くさそうなので capistrano3-puma も puma も v4 系に固定して凌いだ。

Archives ページの npm パッケージも古くなってたので、 React や React Router 、 Webpack 、 Babel など各種ライブラリのバージョンを上げた。 React Router の v5 系から v6 系へのアップデートは結構大変だった。以下を読みながらやった。

withRouter などは React Router から機能が消えるのでそれをラップする関数を自分で書いてコンポーネントに mixin するような感じだった。以前に比べたらマイルドになっているとはいえ、 JavaScript 界隈はアップデートについて行くのが厳しい。

職業プログラマーじゃなくなったので開発環境の維持管理などがおろそかになりがちだし、 Vim やシェルのショートカットを忘れてしまうことがある。 Vim やシェルの操作は特殊技能のようなものなので忘れるともったいない。たまに触って忘れないようにしておきたい。

そういえば温かくなって庭の雑草が伸びてきたので庭の草むしりもやった。ゴールデンメンテナンスウィークだ

| @技術/プログラミング

Archives ページでチャートのカテゴリー選択とセレクトボックスのカテゴリー選択が連動していなかったのを統合して連動するようにした。以前、やり方がわからなくてチャートのカテゴリーのレジェンドをクリックしたときにクリックされたカテゴリーをチャートから非表示にしつつ色をグレーアウトさせるのもできるようになった。どのカテゴリーの記事をいつ頃どのくらい書いていたかがわかるようになってめっちゃ便利。

Archives ページは React で作っていて、チャートとセレクトボックスでそれぞれに別々にカテゴリー一覧を API から取得していたのを一本化し、非表示とするカテゴリーも同じ state として管理するようにした。こういうのがサクッとしかも高速にできて React は便利。 jQuery でやるのは大変だった。

| @技術/プログラミング

OS の設定に応じて自動的にダークモードとライトモードを切り替える(メディアクエリで prefers-color-scheme: light とかやる)ようにしていたが、自分でブログを見ていてダークモード状態で閲覧する時間が短いことに気がついた。考えれば当たり前で夜は寝てるのでダークモードで閲覧する時間が短くなるのは当然だ。個人的には自分のブログはダークモードのときのデザインが気に入っている( 10 年くらい変えてない)ので、 OS のテーマ設定に加えて閲覧者が自分でダークモードかライトモードかを選べるようにした。設定値は Cookie に保持するようにしてる。個人的に便利になった。切り替えは About ページ内か以下の テーマ変更 ボタンでできるようになっている。

| @技術/プログラミング

Lokka の検索はキーワード一つにしか対応していなかった。例えば うどん ラーメン と入力すると、確実に うどん ラーメン という語順で検索が行われる仕様になっている。これはちょっと不便だと思ったので半角スペースでキーワードを分割して AND 検索するようにした。つまり確かに うどん ラーメン という語順で文章が書かれていなくても、 ラーメン うどん という語順だったり、そもそも うどんラーメン が離れたところに書いてあるような文章でもオッケーな仕様にした。 diff はこんな感じ。

一般的な検索システムだと入力された検索キーワードを品詞分解したりして半角スペース入れたりせずともいい感じに検索できるのだろうが、データベースから直接検索するシステムではこれくらいできれば十分かなと思ってる。どうせこのブログで検索してるの自分一人くらいだし。

| @技術/プログラミング

いろいろスパム対策は行っているもののやはりまだスパムが届くので NG ワードの設定を簡単に行えるようにした。こんな感じ。

NG ワード設定
NG ワード設定

これまで一つのテキストフィールドにカンマ区切りで入力しないといけなかったのを、フィールドを分けて単語ごとに入力できるようにした。

モダンなやり方はしてなくて全部サーバーサイドの Ruby でやってる。動的に新規登録フィールドを増やしたりはできない。新規登録したいときは都度都度フォームを保存する必要があるが、十分速いので実用上は全く問題ない。

同様に、スパマーの餌食になっている過去記事のコメント欄を閉鎖する機能も便利にした。

コメント欄を閉じる記事の設定
コメント欄を閉じる記事の設定

仕事では全然プログラミングしていないので久々にコードを書いた。

| @技術/プログラミング

シダの新緑
シダの新緑

最近、ブログに Amazon アソシエイトの広告が表示されなくなっていた。記事の新規公開時だけでなく、最新の価格情報を取得するため 24 時間のみキャッシュして都度新しいデータをとるようにしていたが、商品が 30 日間売れなかったため API へのアクセス権を剥奪されてしまったようだ。アフィリエイト報酬がもらえないのもさみしいが、それよりも記事に商品の画像を表示出来ないのが悲しい。結構頑張って仕組みを作ったのに。

ドキュメントには以下のように書いてあった。

Note that your account will lose access to Product Advertising API 5.0 if it has not generated referring sales for a consecutive 30-day period.

API Rates · Product Advertising API 5.0

これはかなりきびしい。 30 日間でものが売れないことなんてザラにある。 ものが売れない -> API のアクセス権剥奪 -> 商品情報取得できない -> ものが売れない の負のスパイラルに陥ってしまうので基本的には抜け出すことはできない。

Google Adsense といい、個人の泡沫ブログで小銭を稼ぐのがどんどん難しくなっていく。