跳转到内容

区块模型

一个区块就是 blocks 表里的一行。它有标题、Markdown 正文、一个类型、一个父区块,以及在兄弟节点之间的 位置。

字段 类型 说明
id text 主键
title text not null,默认空字符串
slug text 规范化后的短名,未删除的区块之间唯一
content text Markdown 正文
metadata text JSON 字符串——图标、颜色、视图模式
type text 下面七种之一
position text fractional index key,决定兄弟之间的顺序
parent_id text 为 null 时是顶层区块
ref_id text 指向另一个区块:context 子区块用它记下自己引入了哪个区块
created_at / updated_at integer
deleted_at / is_deleted integer 软删除
is_snapshot integer 为 1 时,这一行保存的是某个区块的旧状态

索引是部分索引,条件里带 is_deleted = 0,所以回收站里的东西越多,扫描也不会越贵。

类型 谁创建 怎么渲染
note 你 Markdown 预览,CodeMirror 编辑
prompt 你,或一次运行 提问,旁边挂着模型控件
completion 一次运行 流式写入的答复
agent 你 系统提示词,下面是它的运行记录
craft 你 和 note 一样
script 你 JavaScript 源码编辑器
context 你 指向另一个区块的引用

completion 是唯一不能手工新建的类型——它由模型写回。craft 的渲染和 note 相同,区分的是用途而不是 展示方式。script 现在还不能执行,只存储和高亮。

兄弟顺序来自 position,一个 fractional indexing 的键。要把一个区块插到另外两个中间,OneBook 生成一个 排在两者之间的键,于是这次移动只是一行 UPDATE。不管这一层有多少兄弟,别的区块都不用重新编号。

移动一棵子树时,只有最上面那个区块重新认父。子区块保留自己的 position,所以子树内部的顺序不变。

删除是设 is_deleted 和 deleted_at。这个区块和它的后代从树上消失,但行还在库里。回收站列出被删除子树 的根节点,恢复会把整棵子树连同位置键一起带回来。真正删掉行只有 purge 这一个操作。

提问让 agent 修改某个区块的正文时,OneBook 先把当前状态复制成一个快照子区块:is_snapshot = 1,排在 这个区块所有子区块的最后。旧文本从此就是一个普通区块,能读、能搜、能被链接。

每个区块可以带一个 slug,由标题规范化而来:小写、空白变连字符、去掉标点,写入和读取用的是同一个函数。 正文里 [[slug]] 是链接,((block-id)) 是嵌入。保存时这些引用被抽进 block_links,类型是 block_link 或 block_embed,于是反链查询就是一条普通的 SELECT。