Notion API 开发:以文档为数据库

FreeGuideOnline 最新 2026-06-18

1. 认识 Notion API:为什么把文档当数据库

1.1 传统开发与 Notion 数据库的碰撞

在常规 Web 开发中,我们习惯使用 MySQL、PostgreSQL 或 MongoDB 来存储结构化数据。而 Notion 早已不仅仅是一个笔记工具,它内置了**数据库(Database)**功能,支持属性、筛选、排序等。通过 Notion API,我们可以直接将一个 Notion 数据库当作应用的后台数据源,实现原型搭建、小型后台管理甚至自动化流程。

1.2 以文档为数据库的核心优势

  • 零部署成本:无需购买服务器安装数据库,只需在 Notion 页面中设计好数据库属性。
  • 可视化编辑:团队成员可以直接在 Notion 中修改数据,无需开发后台管理界面。
  • 快速迭代:适合 MVP 开发、内容管理、用户反馈收集等场景。

本教程将带你从零搭建开发环境,通过实操掌握 Notion API 的读写、过滤与排序,最终完成一个“以文档为数据库”的简单留言板应用。

2. 准备工作:获取 API 令牌与创建数据库

2.1 创建 Notion 集成(Integration)

  1. 打开 Notion 开发者页面,点击“新建集成”。
  2. 输入名称(如“我的留言板”),选择关联的工作区,点击“提交”。
  3. 复制生成的 Internal Integration Secret,它类似于数据库密码,请妥善保存。

2.2 为数据库授权集成

Notion 的授权粒度是页面级:

  1. 在 Notion 工作区中新建一个页面,标题为“留言板”。
  2. 在页面内添加一个数据库 - 行内(也可以使用整页数据库),命名为“留言列表”。
  3. 给数据库添加以下属性:
    • 名称(标题栏,默认属性)
    • 内容(文本)
    • 创建时间(创建时间)
  4. 点击页面右上角的“···”,选择“连接”,找到你刚创建的集成,点击连接。这样集成才有权访问该数据库。

2.3 获取数据库 ID

数据库 URL 通常为 https://www.notion.so/workspace/数据库名称?v=xxx,你需要截取中间的一串 32 位字符(不带 ?v= 部分),它就是数据库 ID。例如: https://www.notion.so/xxxx/1234567890abcdef...?v=... 中的 1234567890abcdef... 就是 ID。

3. 环境搭建与第一次请求

3.1 选择你熟悉的开发语言

Notion API 基于 REST,任何能发送 HTTP 请求的语言均可使用。本教程以 Node.js + JavaScript 为例,当然你也可以使用 Python、cURL 等。

初始化项目:

mkdir notion-demo && cd notion-demo
npm init -y
npm install @notionhq/client dotenv

创建 .env 文件:

NOTION_TOKEN=你的集成密钥
NOTION_DATABASE_ID=你的数据库ID

3.2 用 Notion SDK 查询数据库

创建 index.js

const { Client } = require("@notionhq/client");
require("dotenv").config();

const notion = new Client({ auth: process.env.NOTION_TOKEN });
const databaseId = process.env.NOTION_DATABASE_ID;

async function getEntries() {
  const response = await notion.databases.query({ database_id: databaseId });
  // 提取每个条目的名称和内容
  const entries = response.results.map((page) => {
    const props = page.properties;
    const title = props["名称"]?.title[0]?.text?.content || "无标题";
    const content = props["内容"]?.rich_text[0]?.text?.content || "";
    return { title, content, id: page.id };
  });
  console.log(entries);
}

getEntries().catch(console.error);

运行 node index.js,即可在终端看到数据库中所有条目。这证明你已经成功将 Notion 数据库当作数据源读取。

4. 数据库的核心操作:增删改查

4.1 创建新条目(CREATE)

向留言板添加新留言,即创建数据库页面:

async function addEntry(name, contentText) {
  await notion.pages.create({
    parent: { database_id: databaseId },
    properties: {
      "名称": { title: [{ text: { content: name } }] },
      "内容": { rich_text: [{ text: { content: contentText } }] }
    }
  });
  console.log("添加成功");
}

属性名(如“名称”“内容”)必须与数据库中的列名严格一致。

4.2 更新条目(UPDATE)

根据页面 ID 修改内容:

async function updateEntry(pageId, newContent) {
  await notion.pages.update({
    page_id: pageId,
    properties: {
      "内容": { rich_text: [{ text: { content: newContent } }] }
    }
  });
}

4.3 删除条目(删除/归档)

Notion API 支持归档页面,相当于软删除:

async function deleteEntry(pageId) {
  await notion.pages.update({
    page_id: pageId,
    archived: true
  });
}

归档后的条目依然存留,可在 Notion 中手动恢复。

4.4 按条件查询与排序

利用数据库查询参数实现精确筛选:

async function filterByKeyword(keyword) {
  const response = await notion.databases.query({
    database_id: databaseId,
    filter: {
      property: "内容",
      rich_text: { contains: keyword }
    },
    sorts: [{ property: "创建时间", direction: "descending" }]
  });
  // 处理结果...
}
  • filter 支持文本、数字、日期等多种类型。
  • sorts 支持多列排序。

5. 属性类型的处理要点

5.1 标题(title)与富文本(rich_text)

  • 标题属性为 title 数组,需要 results[0].title[0].text.content
  • 富文本同样为 rich_text 数组,内容可能分片,建议拼接所有片段。

5.2 数字、日期与选项

  • 数字:{ number: 42 }
  • 日期:{ date: { start: "2025-04-01" } }
  • 状态/单选:{ select: { name: "已完成" } }
  • 多选:{ multi_select: [{ name: "标签A" }] }

示例:初始化数据库时可添加“状态”列(单选),并在代码中这样更新:

properties: {
  "状态": { select: { name: "待处理" } }
}

6. 实战:构建一个简单的留言板 API

6.1 用 Express 暴露接口

安装 express

npm install express

创建 server.js

const express = require("express");
const { getEntries, addEntry } = require("./notion-operations"); // 封装之前的函数
const app = express();
app.use(express.json());

app.get("/messages", async (req, res) => {
  const entries = await getEntries();
  res.json(entries);
});

app.post("/messages", async (req, res) => {
  const { name, content } = req.body;
  await addEntry(name, content);
  res.status(201).json({ success: true });
});

app.listen(3000, () => console.log("Server running on port 3000"));

这样,前端页面就可以通过 REST 接口读写 Notion 数据库中的留言。

6.2 前端展示与提交(极简版)

一个纯 HTML 示例,直接内嵌于项目:

<!DOCTYPE html>
<html>
<body>
  <h2>留言板</h2>
  <input id="name" placeholder="昵称">
  <textarea id="content"></textarea>
  <button onclick="submitMessage()">提交</button>
  <ul id="list"></ul>
  <script>
    async function loadMessages() {
      const res = await fetch("/messages");
      const data = await res.json();
      document.getElementById("list").innerHTML = data
        .map(m => `<li><b>${m.title}</b>: ${m.content}</li>`)
        .join("");
    }
    async function submitMessage() {
      await fetch("/messages", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          name: document.getElementById("name").value,
          content: document.getElementById("content").value
        })
      });
      loadMessages();
    }
    loadMessages();
  </script>
</body>
</html>

将后端静态文件服务开启,即可拥有一个完全由 Notion 数据库驱动的留言板。

7. 生产环境注意事项与优化

7.1 速率限制与分页

Notion API 有频率限制(通常每秒 3 次请求),生产环境需增加重试逻辑,并对大批量查询使用 start_cursor 分页:

const response = await notion.databases.query({
  database_id: databaseId,
  page_size: 100,
  start_cursor: nextCursor
});

7.2 错误处理

API 可能返回权限错误(404)、格式错误(400)等。务必 try...catch 并解析错误类型:

try {
  await notion.pages.create(...)
} catch (error) {
  if (error.code === 'object_not_found') {
    console.log('数据库未授权或不存在');
  }
}

7.3 安全与只读发布

  • 切勿在前端直接调用 API,密钥必须保存在后端。
  • 若只需展示数据,可开启 Notion 页面的“发布”功能,获取公开链接,结合 unofficial API 解析,但官方 API 是更推荐的安全方式。

8. 扩展思路:从留言板到真正应用

  • 博客系统:用“状态”控制发布/草稿,内容用富文本,实现简单的 CMS。
  • 用户反馈收集:表单提交 -> Notion API -> 数据库,团队成员直接在 Notion 协作处理。
  • 自动化工作流:结合 Zapier、Make 等,监听数据库变化,触发邮件、通知等。

Notion API 让“文档即数据库”成为现实,极大降低了早期项目的开发复杂度。掌握本教程的增删改查、属性处理与工程化实践后,你完全可以尝试将 Notion 作为轻量后端,快速落地你的下一个创意。