本文へ

開発記録

安定したメタデータから関連記事を自動で選ぶ仕組み

このサイトの関連記事の選定ルールをもとに、公開条件、言語、タグの得点、並び順を整理し、自動化で減らせる作業と、編集上の判断が必要な部分を説明します。

林予晴
公開
  • Astro
  • コンテンツエンジニアリング
  • メタデータ
  • 並べ替え

記事末尾の関連記事は、読者が次に知りたいことへ進むための案内になります。記事ごとに一覧を手作業で用意すると、新しい記事を追加するたびに、どの過去記事からリンクするかも考える必要があります。記事が増えるほど、その見直しにも漏れが出やすくなります。

このサイトでは、記事にすでにあるメタデータから候補を集め、決まったルールで少数の記事を選んでいます。私が重視しているのは、なぜそのカードがここに表示されるのか、絶対に含めてはいけない内容は何か、結果がよくないときに何を見直せばよいのかを説明できることです。記事の全文を理解したふりをする必要はありません。

このノートでは、2026年10月25日時点の実装とローカル出力をもとに説明します。扱うのは分類、タグ、日付で並べる小さなルールであり、読者の行動を学習した推薦システムではありません。

まず候補にできる記事を決めます

公開条件を満たすかどうかと、関連性が高いかどうかは別の問題です。

記事ページは、まず getPublishedNotes(locale) を呼び出して、その言語で公開できる記事を取得します。この段階で、下書き、公開日がない記事、公開日が台北時間で当日より後になっている記事を除外し、その後で集合を selectRelatedNotes() に渡します。

後者はさらに、現在の記事とは言語が違う候補と、stableId が現在の記事と同じ候補を除外します。そのため、関連記事に閲覧中の記事そのものが並ぶことも、カード数を埋めるために別の言語の記事が突然出てくることもありません。

この役割分担には注意点があります。selectRelatedNotes() 自体は、下書きかどうかや公開日を確認しません。別の呼び出し元がすべての記事を直接渡しても、この関数が代わりに公開条件で絞り込んでくれるわけではありません。この違いは、条件を設定した検証用データで確認しました。そのため、関数名だけを見て、安全に公開記事を取得できる入口だと考えることはできません。

「ホーム、記事一覧、記事ページ、sitemapで公開クエリを共有する理由」で扱っているのも、同じ公開条件です。関連記事の選定はその条件を適用した後に始まり、そこから「どの記事を先に並べるか」を決めます。

得点は分類と共通のタグで決まります

各候補の得点は、次のルールで決まります。

同じ分類なら 3 点、一致するタグごとに 2 点を加算します。

ここで「同じ」とは、文字列が一致するという意味です。大文字・小文字の変換、同義語の整理、意味解析は行いません。Astro と astro は同じタグにはならず、タイトルに同じ技術名が出てきても、それだけでタグの得点が加わることはありません。

三つの候補がすべて、現在の記事と同じ分類だとします。得点は次のようになります。これはルールを説明するために条件をそろえた例で、実在する三つの記事の効果を比較したものではありません。

候補の条件 分類の得点 タグの得点 合計
共通のタグが二つあり、公開日は比較的古い 3 4 7
共通のタグが一つあり、公開日は比較的新しい 3 2 5
共通のタグがなく、公開日が最も新しい 3 0 3

それでも、最初の候補が先に並びます。日付で順番を決めるのは得点が同じときだけで、新しい記事が、それより得点の高い記事を追い越すことはありません。

この時点でサイトにある分類は development だけなので、同じ言語の候補は分類による得点がすべて同じです。現段階で得点差を生む主な要素はタグです。分類の重みを残しているからといって、複数の分類をまたぐ推薦がすでにできているわけではありません。この重みを、読者調査で最適と確かめられた比率だと説明することもできません。

同点でも予測できる順番にします

並べ替えでは、まず得点、次に publishedAt、最後に stableId を比較します。同点なら公開日時が新しい記事を先にし、公開時刻まで同じときだけ安定した識別子で順番を決めます。

得点と公開時刻をそろえた二つの候補を検証用の集合に入れ、最後は stableId で並ぶことを確認しました。また、関数に渡した集合の元の順番が変わらないことも確かめました。これらは並べ替えの仕様を確認するための検証であり、どちらの記事を読む価値が高いかを証明するものではありません。

順番が安定していると、結果を追いやすくなります。カードの位置が変わったら、推薦システムが「独自の考え」で動いているのではと推測する前に、タグ、日付、候補の集合が変わっていないかを確認できます。

無理に枠を埋める必要はなく、高い関連性も保証されません

関数は、デフォルトでは最大二つの記事を選びます。条件を満たす候補がある分だけ、並べ替えた集合から上限まで取り出し、同じ記事を複製して枠を埋めることはありません。記事テンプレートも、一覧が空でないときだけ関連記事のセクションを出力します。下書きのプレビューでは、この一覧自体を作りません。

ただし、この実装には最低得点の基準がありません。共通のタグがなくても、候補の集合に残っていれば選ばれることがあります。分類が一つだけの状態では、こうした候補にも同じ分類の得点が付き、その後は日付で並びます。

そのため、カードが表示されたという事実から分かるのは、その記事がこの実装の候補選定と並べ替えのルールを通ったことだけです。次に読むのに最適な記事だと確認されたわけではありません。記事が増え、関連性の低い候補が繰り返し表示されるようになって初めて、最低得点の基準や手動での指定を検討する理由が生まれます。まだ起きていない問題に備えて、先に大がかりな設定を用意する必要はありません。

自動生成した一覧にも編集上の判断は必要です

タグを並べ替えに使うなら、タグは記事の上に添える飾りではなくなります。タグの表記を変えると、どの記事同士が近くに並ぶかも変わる可能性があります。広すぎるタグを無造作に増やすと、もともと違うテーマまで同じくらい関連しているように見えてしまいます。

メタデータを変えるかどうかは、まず記事が実際に答えている問いを確認してから判断します。どちらも「検証」を扱っていても、一方は公開用の出力を確認する方法、もう一方は AI が判断を誤った後に結論を取り下げる方法を説明しているとします。同じタグを付けられても、それだけで互いの代わりになる記事とはいえません。

このルールは、全文を読まず、クリックを追跡せず、読者の前提知識も判別しません。入門記事の後に応用記事を推薦する順番も保証しません。読み進める順番をはっきり示したいときは、理由を添えた本文中のリンクのほうが、自動生成した一覧よりも、その先を読む意味を伝えられます。

メタデータを変えると、次のビルド結果も変わります

関連記事は、Astro が記事の HTML を生成するときに決まります。カード自体は通常のリンクなので、ブラウザーが推薦サービスからデータを取得するのを待つ必要はありません。その代わり、記事の追加、タグの調整、公開可否の変更を行った後は、静的ページを再ビルドしてデプロイするまで、既存ページの一覧は更新されません。

ローカルでの確認では、実際の公開記事の集合から想定される一覧を計算し、HTML のセマンティクスを扱った記事の各言語のページで、二つのカードとその順番を照合しました。三言語とも結果は一致しました。これで確認できるのは、選んだページの出力にこのルールが適用されていることです。クリックの分析はしていないため、この推薦で閲覧数が増えたとまではいえません。

まずは、選定理由を説明できるこの一覧を維持する方針です。具体的なミスマッチが出てきたら、メタデータが不正確なのか、並べ替えのルールが足りないのか、それとも読者には人の手で組み立てた読み進め方が必要なのかを判断します。