数据库

Notion


Notion 提供了一个多功能、开箱即用的解决方案来管理您的数据。

Notion Wrapper 是一个 WebAssembly(Wasm) 外部数据包装器,允许您读取 Notion 工作区中的数据,并在 Postgres 数据库中使用。

可用版本#

版本Wasm 包 URL校验和必需的 Wrappers 版本
0.2.0https://github.com/supabase/wrappers/releases/download/wasm_notion_fdw_v0.2.0/notion_fdw.wasm719910b65a049f1d9b82dc4f5f1466457582bec855e1e487d5c3cc1e6f986dc6>=0.5.0
0.1.1https://github.com/supabase/wrappers/releases/download/wasm_notion_fdw_v0.1.1/notion_fdw.wasm6dea3014f462aafd0c051c37d163fe326e7650c26a7eb5d8017a30634b5a46de>=0.4.0
0.1.0https://github.com/supabase/wrappers/releases/download/wasm_notion_fdw_v0.1.0/notion_fdw.wasme017263d1fc3427cc1df8071d1182cdc9e2f00363344dddb8c195c5d398a2099>=0.4.0

准备#

在您查询 Notion 之前,需要启用 Wrappers 扩展,并将您的凭据存储在 Postgres 中。

启用 Wrappers#

确保 wrappers 扩展已安装在您的数据库上

1
create extension if not exists wrappers with schema extensions;

启用 Notion Wrapper#

启用 Wasm 外部数据包装器

1
create foreign data wrapper wasm_wrapper
2
handler wasm_fdw_handler
3
validator wasm_fdw_validator;

存储您的凭据(可选)#

默认情况下,Postgres 将 FDW 凭据以明文形式存储在 pg_catalog.pg_foreign_server 中。任何访问此表的人都可以查看这些凭据。Wrappers 旨在与 Vault 配合使用,Vault 为存储凭据提供额外的安全级别。我们建议使用 Vault 存储您的凭据。

1
-- Save your Notion API key in Vault and retrieve the created `key_id`
2
select vault.create_secret(
3
'<Notion API key>', -- Notion API key, should look like ntn_589513........
4
'notion',
5
'Notion API key for Wrappers'
6
);

⚠️ ** 获取 Notion API 密钥**

  1. 访问 Notion > 个人资料 > 集成
  2. 点击 新建集成
  3. 添加集成名称,选择您的工作区,然后选择 Internal 作为类型
  4. 这将为您提供一个 Internal Integration Secret,看起来像 ntn_589513........
  5. 将其用作您的 Notion API 密钥

连接到 Notion#

我们需要向 Postgres 提供访问 Notion 的凭据和任何其他选项。我们可以使用 create server 命令来执行此操作

1
create server notion_server
2
foreign data wrapper wasm_wrapper
3
options (
4
fdw_package_url 'https://github.com/supabase/wrappers/releases/download/wasm_notion_fdw_v0.1.1/notion_fdw.wasm',
5
fdw_package_name 'supabase:notion-fdw',
6
fdw_package_version '0.1.1',
7
fdw_package_checksum '6dea3014f462aafd0c051c37d163fe326e7650c26a7eb5d8017a30634b5a46de',
8
api_url 'https://api.notion.com/v1', -- optional
9
api_key_id '<vault key_ID>' -- the Vault key id from the previous step, not the Notion API key itself
10
);

请注意,fdw_package_* 选项是必需的,用于指定 Wasm 包元数据。您可以从 上方 获取可用的包版本列表。

创建模式#

我们建议创建一个模式来保存所有外部表

1
create schema if not exists notion;

选项#

完整的外部表选项如下

  • object - Notion 中的对象名称,必需。

支持的对象如下所示

对象名称
block
page
database
user

实体#

我们可以使用 SQL import foreign schema 导入来自 Notion 的外部表定义。

例如,使用下面的 SQL 可以自动在 notion 模式中创建外部表。

1
-- create all the foreign tables
2
import foreign schema notion from server notion_server into notion;
3
4
-- or, create selected tables only
5
import foreign schema notion
6
limit to ("blocks", "pages")
7
from server notion_server into notion;
8
9
-- or, create all foreign tables except selected tables
10
import foreign schema notion
11
except ("blocks")
12
from server notion_server into notion;

Block#

这是一个表示 Notion Block 内容的对象。

参考:Notion API 文档

操作#

对象选择插入更新删除截断
Block

用法#

1
create foreign table notion.blocks (
2
id text,
3
page_id text,
4
type text,
5
created_time timestamp,
6
last_edited_time timestamp,
7
archived boolean,
8
attrs jsonb
9
)
10
server notion_server
11
options (
12
object 'block'
13
);

说明#

  • attrs 列包含所有用户属性,格式为 JSON。
  • page_id 字段由 FDW 添加,方便开发。
  • 所有块,包括嵌套的子块,都属于同一页面,将具有相同的 page_id
  • idpage_id 列都支持查询下推
  • 使用 page_id 过滤器来递归地获取特定页面的所有块
  • 由于递归数据请求,不带过滤器的查询所有块可能需要很长时间

Page#

这是一个表示 Notion 页面的对象。

参考:Notion API 文档

操作#

对象选择插入更新删除截断
Page

用法#

1
create foreign table notion.pages (
2
id text,
3
url text,
4
created_time timestamp,
5
last_edited_time timestamp,
6
archived boolean,
7
attrs jsonb
8
)
9
server notion_server
10
options (
11
object 'page'
12
);

说明#

  • attrs 列包含所有页面属性,格式为 JSON。
  • id 列支持查询下推

Database#

这是一个表示 Notion 数据库的对象。

参考:Notion API 文档

操作#

对象选择插入更新删除截断
数据库

用法#

1
create foreign table notion.databases (
2
id text,
3
url text,
4
created_time timestamp,
5
last_edited_time timestamp,
6
archived boolean,
7
attrs jsonb
8
)
9
server notion_server
10
options (
11
object 'database'
12
);

说明#

  • attrs 列包含所有数据库属性,格式为 JSON。
  • id 列支持查询下推

User#

这是一个表示 Notion 用户对象。

参考:Notion API 文档

Operations#

对象选择插入更新删除截断
User

Usage#

1
create foreign table notion.users (
2
id text,
3
name text,
4
type text,
5
avatar_url text,
6
attrs jsonb
7
)
8
server notion_server
9
options (
10
object 'user'
11
);

Notes#

  • attrs 列包含所有用户属性,格式为 JSON。
  • id 列支持查询下推
  • 可以使用以下方法提取用户电子邮件:attrs->'person'->>'email'

查询下推支持#

此 FDW 支持使用 id 作为过滤器的 where 子句下推。例如,

1
select * from notion.pages
2
where id = '5a67c86f-d0da-4d0a-9dd7-f4cf164e6247';

将被转换为 Notion API 调用:https://api.notion.com/v1/pages/5a67c86f-d0da-4d0a-9dd7-f4cf164e6247

除了 id 列下推之外,还支持 Block 对象的 page_id 列下推。例如,

1
select * from notion.blocks
2
where page_id = '5a67c86f-d0da-4d0a-9dd7-f4cf164e6247';

将递归地获取 ID 为 '5a67c86f-d0da-4d0a-9dd7-f4cf164e6247' 的页面的所有子块。这可以大大减少 API 调用次数并提高查询性能。

支持的数据类型#

Postgres 数据类型Notion 数据类型
booleanBoolean
text字符串
timestampTime
timestamptzTime
jsonbJson

Notion API 使用 JSON 格式的数据,请参阅 Notion API 文档 以获取更多详细信息。

限制#

本节描述了在使用此 FDW 时需要注意的重要限制和注意事项

  • 由于需要完全的数据传输,大型结果集可能会遇到较慢的性能
  • 查询下推支持仅限于 'id' 和 'page_id' 列
  • 对于大型页面层次结构,递归块获取可能非常慢
  • 使用这些外部表的物化视图在逻辑备份期间可能会失败

示例#

基本示例#

此示例将在您的 Postgres 数据库中创建一个“外部表”并查询其数据。

1
create foreign table notion.pages (
2
id text,
3
url text,
4
created_time timestamp,
5
last_edited_time timestamp,
6
archived boolean,
7
attrs jsonb
8
)
9
server notion_server
10
options (
11
object 'page'
12
);
13
14
-- query all pages
15
select * from notion.pages;
16
17
-- query one page
18
select * from notion.pages
19
where id = '5a67c86f-d0da-4d0a-9dd7-f4cf164e6247';

attrs 是一个特殊列,它以 JSON 格式存储所有对象属性,您可以从中提取所需的任何属性。请参阅下面的更多示例。

查询 JSON 属性#

1
create foreign table notion.users (
2
id text,
3
name text,
4
type text,
5
avatar_url text,
6
attrs jsonb
7
)
8
server notion_server
9
options (
10
object 'user'
11
);
12
13
-- extract user's email address
14
select id, attrs->'person'->>'email' as email
15
from notion.users
16
where id = 'fd0ed76c-44bd-413a-9448-18ff4b1d6a5e';

查询 Blocks#

1
-- query ALL blocks of ALL pages recursively, may take long time!
2
select * from notion.blocks;
3
4
-- query a single block by block id
5
select * from notion.blocks
6
where id = 'fc248547-83ef-4069-b7c9-18897edb7150';
7
8
-- query all block of a page by page id
9
select * from notion.blocks
10
where page_id = '5a67c86f-d0da-4d0a-9dd7-f4cf164e6247';