zpaper-draft

Type to search...

to open search from anywhere

キーワード検索

ブログのキーワード検索機能の実装概要。検索インデックス、API、キーワード分析。

ブログに組み込まれた全文キーワード検索機能です。MiniSearchを使用し、ビルド時に生成した検索インデックスをもとに記事を検索します。

アーキテクチャ

検索機能は以下のコンポーネントで構成されています。

  • 検索インデックス生成 — ビルド時にMDX記事ファイルからsearch-index.jsonを生成(generate-search-index.mjs
  • 検索API — Cloudflare Pages Functionによる全文検索API(GET /api/search?q=...
  • 検索ページ — クライアントサイドの検索UI(/search/
  • キーワードログ — 検索クエリをCloudflare KVに記録し、分析に活用
  • キーワードビューア — ログを可視化するダッシュボードアプリ
  • 開発時フォールバック — クライアントサイドMiniSearchによるローカル検索

検索インデックス

blog/scripts/generate-search-index.mjsがビルド時に記事ファイルを読み取り、search-index.jsonを生成します。生成されたファイルは2箇所に配置されます。

出力先用途
blog/public/search-index.json開発環境でのクライアントサイド検索用
functions/pj/zpaper/api/search-data.json本番環境のCloudflare Pages Function用

各記事ドキュメントのフィールド構成は以下の通りです。

フィールド説明
id記事の一意識別子
slug記事のURLスラッグ
title記事タイトル
description記事の説明文
tagsタグ(スペース区切り)
createdAt作成日
excerpt記事本文の先頭500文字のプレーンテキスト

インデックスはcreatedAtの降順でソートされます。

検索機能

MiniSearchの検索オプションによって以下の検索動作が有効になっています。

機能設定値説明
前方一致検索prefix: true入力途中の部分文字列でも検索結果を返す
あいまい検索fuzzy: 0.2タイプミスや表記揺れに対して許容度0.2でマッチングする

フィールドごとにブースト値が設定されており、検索結果のランキングに重み付けが行われます。

フィールドブースト値
title3.0
description2.0
tags1.5
excerpt1.0(デフォルト)

検索結果には、マッチしたキーワードが<mark>タグでハイライトされたタイトルと抜粋が含まれます(highlighted_titlehighlighted_excerpt)。

検索ページ

  • パス: /search/
  • URLパラメータ: ?q=検索クエリ
  • 入力は300msのデバウンス付き
  • URLは検索クエリと同期される
  • ページロード時に入力フィールドへ自動フォーカス

キーワードログ

検索APIは、検索が実行されるたびにクエリ情報をCloudflare KVに記録します。

仕組み

検索関数(functions/pj/zpaper/api/search.ts)内で、検索結果の計算後に非同期でKVに書き込みます。

  • 記録条件: 検索結果が1件以上ある場合のみ(ゼロヒットのクエリは記録しない)
  • 書き込み方式: Fire-and-forget(書き込み失敗が検索レスポンスに影響しない)
  • ストア名: keyword-logs
  • キー形式: <ISO-timestamp>-<6文字ランダム>(例: 2026-03-01T12:34:56.789Z-a3f7kz

各ログエントリのデータ構成は以下の通りです。

フィールド説明
keyword検索クエリ文字列
timestamp検索実行時のISO 8601タイムスタンプ
resultCount検索結果の件数

開発環境での挙動

開発環境(pnpm dev)ではクライアントサイドで検索が実行されるため、Cloudflare Pages Functionは呼ばれず、キーワードログは記録されません。

キーワードビューア

キーワードログを可視化するためのダッシュボードアプリです。2つの形態があります。

Webアプリ(sub-packages/keyword-viewer)

React + Viteで構築されたSPAです。

cd sub-packages/keyword-viewer
pnpm dev   # http://localhost:60521 で起動

開発時はViteのプロキシ設定により、APIリクエストが本番サイト(zudo-paper.pages.dev)に転送されます。APIが利用できない場合は、シード付きのモックデータにフォールバックします。

画面構成

パス画面内容
/ダッシュボード検索総数、ユニークキーワード数、本日/今週の検索数、上位キーワードチャート、日別検索ボリュームチャート
/keywordsキーワード一覧全キーワードのテーブル表示(件数、最終検索日でソート可能)
/calendarカレンダー月別/週別の検索ボリュームをヒートマップ表示(日ごとのキーワード内訳も確認可能)

技術スタック

React 19、React Router DOM v7、Vite 6、Tailwind CSS v4、Mermaid v11(チャート描画)。

API