iT邦幫忙

2025 iThome 鐵人賽

DAY 9
1
AI & Data

Notion遇上LLM:30天打造我的AI知識管理系統系列 第 9

【Day 9】設計 SQLite Schema:把 Notion JSON 轉成結構化資料

  • 分享至 

  • xImage
  •  

Day 8,我們已經完成了 Notion Pipeline,可以一次抓取多個 Database,並把 PageBlock 展平成乾淨 JSON
JSON 畢竟是半結構化格式,如果我們要進一步做檢索、查詢、甚至接上向量資料庫,就需要一個「結構化資料庫」來支撐。這就是 SQLite Schema 設計的目的。

1. 為什麼選擇 SQLite?

在眾多資料庫選項(MySQL、PostgreSQL…)中,我們先從 SQLite 開始,主要原因有以下幾點:

  • 輕量級:單一檔案即可儲存,適合 Demo 與本地開發。
  • 結構清晰:適合做資料清理與正規化,後續能無痛切換到 MySQL、Postgres。
  • 易於整合:Python 內建 sqlite3,不用額外安裝伺服器。
  • 中繼層:SQLite 可作為「中間儲存」,之後再將乾淨資料送進向量資料庫(例如 Chroma, Weaviate)。

🔗 相關資源

2. SQLite Table Schema

下面設計了三個主要 Table,對應 Notion 的 Database → Page → Block 三層結構。

-- 1) 儲存 Notion Database 的基本資訊
CREATE TABLE notion_databases (
    database_id      TEXT PRIMARY KEY,   -- Notion Database UUID
    database_name    TEXT NOT NULL,      -- Database 名稱
    category         TEXT,               -- 自訂分類:Life / Work / Learning
    created_time     TEXT,               -- Database 建立時間
    last_edited_time TEXT                -- Database 最後編輯時間
);

-- 2) 儲存屬於某個 Database 的 Page
CREATE TABLE notion_pages (
    page_id          TEXT PRIMARY KEY,   -- Notion Page UUID
    page_name        TEXT,               -- Page 標題(Notion title property)
    database_id      TEXT NOT NULL,      -- 關聯的 Database ID(FK)
    created_time     TEXT,               -- Page 建立時間
    last_edited_time TEXT,               -- Page 最後編輯時間
    FOREIGN KEY(database_id) REFERENCES notion_databases(database_id)
);

-- 3) 儲存 Page 裡的 Block(Notion 最小單位:文字、標題、程式碼、清單等)
CREATE TABLE notion_blocks (
    block_id         TEXT PRIMARY KEY,   -- Notion Block UUID
    page_id          TEXT NOT NULL,      -- 所屬的 Page ID(外鍵)
    order_index      INTEGER,            -- Block 在 Page 裡的順序(流水號)
    block_type       TEXT,               -- Block 類型(paragraph, heading_2, code...)
    block_text       TEXT,               -- Block 主要文字內容(如段落、程式碼)
    code_language    TEXT,               -- 程式碼區塊語言(僅 type=code 時有值,其餘可 NULL)
    created_time     TEXT,               -- Block 建立時間
    last_edited_time TEXT,               -- Block 最後編輯時間
    FOREIGN KEY(page_id) REFERENCES notion_pages(page_id)
);

💡 設計說明

  1. 分層結構(對應 Notion 的三層資料)
    • notion_databases → 存放各個 Database 的基礎資料(相當於「表格集合」)。
    • notion_pages → 每個 Database 下的 Page,相當於一筆 row + 詳細內容。
    • notion_blocks → Page 裡的最小單位,保證筆記細節不會遺失。
      這樣的三層設計可以 保持關聯,又能在需要時做 單獨查詢。
  2. 欄位命名
    • 帶上前綴(database_idpage_idblock_id),避免混淆。
    • Block 類型特別分成 block_typecode_language,讓檢索程式碼更方便。
  3. 時間欄位
    • 建議存 ISO 8601 UTC 格式(如 2025-09-20T12:34:56Z)。
    • 方便之後做同步與增量更新。
  4. 延伸應用
    • 想查詢某個 Database 下所有的程式碼 Block:
          SELECT p.page_name, b.block_text, b.code_language
          FROM notion_blocks b
          JOIN notion_pages p ON b.page_id = p.page_id
          WHERE b.block_type = 'code' AND b.code_language = 'python';
      
    • 統計不同類別 Database 的 Page 數量:
      SELECT d.category, COUNT(p.page_id) AS page_count
      FROM notion_databases d
      JOIN notion_pages p ON d.database_id = p.database_id
      GROUP BY d.category;
      

3. ERD 設計

在前面我們已經定義了三張資料表的 Schema。為了更直觀理解它們之間的關聯,下面我們將其轉換成 ERD(Entity Relationship Diagram)
https://ithelp.ithome.com.tw/upload/images/20250923/20178104lIH9vk5pMf.png

🔎 關係說明

  • notion_databasesnotion_pages (1:N)
    一個 Database 可以有多個 Page,每個 Page 必須隸屬於一個 Database
  • notion_pagesnotion_blocks (1:N)
    一個 Page 可以包含多個 Block,每個 Block 必須對應到一個 Page

小結與下篇預告

今天,我們完成了 SQLite Schema 設計,將 Notion 的 JSON 資料對應到 Database → Page → Block 的三層結構。這讓我們能夠用 SQL 直接查詢 Notion 筆記,甚至針對程式碼或特定分類做分析。

不過,在把 JSON 匯入資料庫之前,還需要進一步調整資料結構:

  • 補充唯一識別:加入 block_idorder_index,確保每個 BlockPage 內有固定順序。
  • 時間欄位正規化:將 created_timelast_edited_time 轉成標準 ISO 格式,方便增量更新與比對。
  • 欄位對應清理:確保 JSON 的 key 與資料表 schema 一致,避免寫入錯誤。

在 Day 10,我們會針對這些需求,實作一版資料清理與轉換程式,讓 Pipeline 產生的 JSON 能無縫寫入 SQLite,完成從 Notion → JSON → Database 的完整流程。


上一篇
【Day 8】實作 Notion 自動化 Pipeline:一次抓取多個 Database → Page → Block
系列文
Notion遇上LLM:30天打造我的AI知識管理系統9
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言