ここは あなたOS のワークフローをそのままデータ構造に落とし込むのが最も美しい。
以下は「ニュース → 分類 → 特許請求項 → 下書き → OR選択 → 投稿」という流れを 最小状態遷移モデルとして整理したデータベース設計です。
構造は 5つの主要テーブル + 2つの補助テーブルで完結します。
🧱 データベース設計(テーブル定義)
1. news_items(ニュース記事の原文ストア)
外界から入ってくる「生データ」。
OS の Input Buffer に相当。
CREATE TABLE news_items (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
external_id VARCHAR(255) NOT NULL, -- RSSのGUIDやURLハッシュ
title TEXT NOT NULL,
url TEXT NOT NULL,
source VARCHAR(255),
published_at DATETIME,
content MEDIUMTEXT, -- 本文(全文 or 抽出)
fetched_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY (external_id)
);
2. classifications(事故/警鐘/失敗の分類結果)
Gemini の一次解釈。
あなたOS の「意味レイヤー」。
CREATE TABLE classifications (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
news_id BIGINT NOT NULL,
category ENUM('事故','警鐘','失敗','その他') NOT NULL,
reason TEXT, -- なぜその分類になったか
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (news_id) REFERENCES news_items(id)
);
3. patent_drafts(技術特許/政策特許の請求項生成)
Gemini の二次解釈。
あなたOS の「変換レイヤー(IR生成)」。
CREATE TABLE patent_drafts (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
news_id BIGINT NOT NULL,
classification_id BIGINT NOT NULL,
kind ENUM('技術特許','政策特許') NOT NULL,
summary TEXT, -- 特許の要約
claims JSON NOT NULL, -- ["請求項1...", "請求項2..."]
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (news_id) REFERENCES news_items(id),
FOREIGN KEY (classification_id) REFERENCES classifications(id)
);
4. blog_drafts(はてなブログ投稿用の下書き)
あなたが OR 選択するための 中間バッファ。
あなたOS の「意思決定レイヤー」。
CREATE TABLE blog_drafts (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
patent_draft_id BIGINT NOT NULL,
title TEXT NOT NULL,
body MEDIUMTEXT NOT NULL,
status ENUM('pending','approved','posted','discarded')
NOT NULL DEFAULT 'pending',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (patent_draft_id) REFERENCES patent_drafts(id)
);
5. posted_logs(実際に投稿された記事のログ)
Output Layer(I/Oデバイス)
はてなブログ AtomPub の結果を記録。
CREATE TABLE posted_logs (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
blog_draft_id BIGINT NOT NULL,
hatena_entry_id VARCHAR(255) NOT NULL,
posted_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (blog_draft_id) REFERENCES blog_drafts(id)
);
🔧 補助テーブル
6. processed_news(重複処理防止)
ニュース巡回時の Dedup 用。
CREATE TABLE processed_news (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
external_id VARCHAR(255) NOT NULL,
processed_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY (external_id)
);
7. system_settings(巡回設定・APIキーなど)
アプリ設定の保存。
CREATE TABLE system_settings (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL UNIQUE,
value TEXT NOT NULL
);
🧩 全体の状態遷移(あなたOSのミニマルモデル)
news_items
↓ (分類)
classifications
↓ (特許生成)
patent_drafts
↓ (ブログ下書き)
blog_drafts (pending)
↓ あなたの OR 選択
blog_drafts (approved)
↓ AtomPub 投稿
posted_logs
この 直線的な状態遷移 があなたの OS と完全に一致している。
🌱 あなたの OS に合わせた特徴
1. 意味レイヤーと構造レイヤーを分離
- news_items = 生データ
- classifications = 意味
- patent_drafts = 構造化(請求項IR)
- blog_drafts = 出力フォーマット
あなたの「意味と構造の分離」思想をそのまま反映。
2. OR 選択を中心に据えた設計
あなたの OS の核は「AI はスカウト、あなたが OR 選択」。
そのため:
- blog_drafts.status = pending → approved → posted
という 人間中心の状態遷移を採用。
3. 請求項は JSON 配列で保持
あなたの「IR(中間表現)としての請求項」をそのまま保持できる。
✨ 次に進むなら
- API 設計(REST / GraphQL)
- バックエンド構成(FastAPI / Flask / Rails)
- Review UI のワイヤーフレーム
- はてなブログ投稿モジュールの実装
どこを深掘りしたい?