ツアー ↔ ライブアルバム 紐づきチェック 運用ドキュメント
概要
scripts/find-missing-tour-album-links.ts は、ツアーデータとライブアルバムリリースデータの紐づき状況を確認するためのスクリプトである。
紐づきが不足している組み合わせを洗い出し、手動でのデータ補完作業(Neon DB 更新)を支援する。
データアーキテクチャ
このスクリプトが参照するデータは 2 つの異なるストア に分散して保存されている。
| データ種別 | 保存先 | 取得方法 | 主キーフィールド |
|---|---|---|---|
ツアー(tours テーブル) |
Neon DB(Prisma) | DATABASE_URL 経由で SQL クエリ |
tourId(例: 2022B) |
| ライブアルバム(releases) | Vercel Blob(releases.json) |
RELEASES_BLOB_URL を fetch |
id(例: rg-xxxxxxxx-xxxx) |
重要: releases のフィールドは
idでありreleaseIdではない。lib/blob.tsのgetReleasesFromBlob()やtypes/release.tsのReleaseSchemaと一致している。
紐づきの仕組み
tours テーブル(Neon)
tourId: "2022B"
title: "モーニング娘。'22 コンサートツアー ..."
releaseId: "rg-xxxxxxxx-xxxx" ← Blob releases の id を参照
│
▼
releases.json(Blob)
id: "rg-xxxxxxxx-xxxx"
title: "モーニング娘。'22 コンサートツアー ... LIVE"
format: "live"
tours.releaseId が NULL の場合、そのツアーはライブアルバムと紐づいていない。
チェックロジック
① ツアーあり・ライブアルバムなし
const toursWithoutAlbum = tours.filter((t) => !t.releaseId);
tours.releaseId が NULL のツアーが対象。
② ライブアルバムあり・対応ツアーなし
const tourReleaseIds = new Set(
tours.map((t) => t.releaseId).filter(Boolean) as string[]
);
const albumsWithoutTour = liveReleases.filter((r) => !tourReleaseIds.has(r.id));
Blob の format: 'live' なリリースのうち、どのツアーの releaseId にも一致しないものが対象。
参考: 紐づき済みの組み合わせ確認
for (const t of tours.filter((t) => t.releaseId)) {
const album = liveReleases.find((r) => r.id === t.releaseId);
const albumTitle = album ? album.title : '(Blob に存在しない)';
console.log(` ${t.tourId} → ${t.releaseId} ${albumTitle}`);
}
liveReleases.find((r) => r.id === t.releaseId) で一致を検索する。
r.id と t.releaseId を比較することが正しい。
既知の問題と修正履歴
Issue #681: type Release のフィールド名ミス(2026-04-20 修正)
症状: スクリプト実行時、手動で紐づけ済みのツアーがすべて「Blob に存在しない」と表示され、ほぼ全件が未紐づけと誤判定された。
根本原因: スクリプト内のローカル型定義が誤っていた。
// ❌ 修正前: releaseId は存在しないフィールド → 常に undefined
type Release = { releaseId: string; title: string; format: string };
// ✅ 修正後
type Release = { id: string; title: string; format: string };
影響箇所:
| 箇所 | 誤り | 正しい記述 |
|---|---|---|
liveReleases.map((r) => r.releaseId) |
r.releaseId が常に undefined |
r.id |
!tourReleaseIds.has(r.releaseId) |
全件 true になり全アルバムが未紐づけ判定 |
!tourReleaseIds.has(r.id) |
liveReleases.find((r) => r.releaseId === t.releaseId) |
永遠に一致しない | r.id === t.releaseId |
console.log(\ ${r.releaseId} ${r.title}`)` |
undefined が出力される |
r.id |
実行手順
# .env.local に以下を設定
# DATABASE_URL=...
# RELEASES_BLOB_URL=...
bun --env-file=.env.local run scripts/find-missing-tour-album-links.ts
出力の見方
============================================================
【① ツアーあり・ライブアルバムなし】 (X 件)
============================================================
2024B モーニング娘。'24 MOTTO MORNING MUSUME。
...
→ tours.releaseId が NULL。対応するライブアルバムの id を調べて UPDATE する。
============================================================
【② ライブアルバムあり・対応ツアーなし】 (X 件)
============================================================
rg-xxxxxxxx モーニング娘。コンサートツアー ○○ LIVE
...
→ Blob にはあるがどのツアーにも紐づいていない。ツアーを新規追加するか既存ツアーに紐づける。
--- 参考: 現在紐づき済みの組み合わせ ---
2022B → rg-xxxxxxxx モーニング娘。'22 コンサートツアー ... LIVE
...
→ "(Blob に存在しない)" と表示された場合、tours.releaseId に設定された id が Blob の releases に存在しない。
データ補完手順
ツアーにライブアルバムを紐づける
- ②の出力からライブアルバムの
idと対応するツアーを特定する - Neon DB の
toursテーブルを更新する
UPDATE tours SET "releaseId" = 'rg-xxxxxxxx-xxxx' WHERE "tourId" = '2022B';
対応ツアーがないライブアルバムへの対処
- ツアーデータが存在しない場合:
toursテーブルに新規レコードを追加する - 既存ツアーと実質同一の場合: 既存ツアーの
releaseIdを更新する