Elasticsearch → Static JSON / D1 移行検証 — 小規模データなら全文検索エンジンは不要だった
Cloudflare Pages上で動くNext.js製の日本語テキスト検索APIで、Elasticsearchの代替としてCloudflare D1(SQLite)とStatic JSON(インメモリ検索)を実装し、3方式の検索性能を比較しました。 背景 古典日本語テキストの全文検索APIを運用しています。Elasticsearchを外部クラスタとして利用していましたが、以下の理由で代替を検討しました。 外部サービスへの依存を減らしたい Cloudflare Pages内で完結させたい データ量が小さい(約1,800件)ので、全文検索エンジンは過剰かもしれない データ規模 項目 値 レコード数 1,812件 テキスト総量(UTF-8) 約2.5 MB 1レコード平均 約1.4 KB 各レコードは古典日本語テキスト(数行〜十数行)、ページ番号、巻名、IIIFキャンバスURLで構成されています。 3方式の概要 1. Elasticsearch(既存) 外部Elasticsearchクラスタに対して、fetch APIでwildcardクエリを実行する方式です。 { wildcard: { 'original_text_lines.keyword': `*${query}*` } } ngramアナライザーでインデクシングしていますが、実際の検索ではwildcardクエリ(*query*)を使っており、ngramインデックスの恩恵を受けていませんでした。 2. Cloudflare D1(SQLite) Cloudflare D1にデータを格納し、LIKEで部分一致検索する方式です。 SELECT id, page, original_text, vol_str, canvas FROM texts WHERE original_text LIKE '%検索語%' ORDER BY page ASC LIMIT 20 OFFSET 0 集計(ファセット)はSQLのGROUP BYで実現します。 SELECT vol_str, COUNT(*) as doc_count FROM texts WHERE original_text LIKE '%検索語%' GROUP BY vol_str ORDER BY vol_str ASC D1のbatch()APIで検索・カウント・集計の3クエリを同時実行できます。 ...