将数据库关联到 schema,Entity Enricher 便会将您扩充后的实体维护为由您拥有的关系表:一张真正的 company 表,带有 revenue 列 —— 而非导出文件。只需下载一次即可运行的 SQL 快照,然后通过由幂等 upsert 组成的增量馈送让数据库持续保持收敛。
一次存储,按需投影。 富化会将当前实体状态写入实体层;每个关联的数据库都是该状态的一个投影,以一次性快照加上你需确认的增量数据流的形式交付。编辑 schema 只需重新投影,而无需数据迁移。
database_sync: false);其他用户的增强仍会正常路由。.sql 快照(包含表和数据)并将其应用到您的 PostgreSQL。该 DDL 附带联接索引和外键(删除实体时,子记录和关联记录会级联删除)。文件头会告诉您应从哪个增量游标处继续。每种实体类型都有一个数据库键——即你的表用作唯一索引和 upsert 冲突目标的列组合。链接数据库时,AI 分类流程会为你提出完整的数据库模型(键、列类型、索引、归属)供你审核,并按简单的优先级回退:优先使用对象的语义 ID(如果有),否则使用类 Id 字段(id、product_id 等),再否则使用对象的自然键。在你的表中,语义 ID 会以semantic_id列的形式出现——id 这个名称仍可留作自用。你可以随时在数据库的“模型”标签页中修改它们——一经发布,这属于迁移级变更:之后请重新下载快照。在从该标签页发布模式之前,不会有任何内容进入你的数据库(仅链接不会创建任何表或行)。
数据库键永不可空。null 值匹配不到任何行,因此它不会更新实体,而会在每次丰富化时插入一条新的重复记录——这也是键返回为空的丰富化会被拒绝而非保存的原因。编辑器将这两个标志区分开,同时设置两者的 schema 在保存或关联数据库时会被拒绝,并会说明两种修复方式:让该属性始终存在,或将该类型的键设为另一个属性。
当数据库键是增强后的文本字段而非语义 ID 时,存储的值将是模型给出的答案,而不是你发送的文本。在请求中把某公司标识为 Embraer 并不能固定该字段:增强结果可能返回 Embraer S.A.——修正后的拼写、补全的法律后缀、去掉的消歧词——而这才是该行的键。因此用你发送的值去查找该行可能找不到(请使用随每次已保存增强结果一起返回的 entity_keys),而后续运行若表述不同就是另一个键——它会插入第二行,而不是更新你的那一行。任何由增强文本构成的键都会如此。解决办法是为该类型启用语义 ID:同一名称的各种变体会解析为单一稳定标识,因此无论模型如何拼写,该行都能保留。请在生成架构时就启用它——之后再添加意味着要修改每个对象。
数组内嵌套的对象会成为各自独立的表,并通过联结行保留顺序;没有标识的值对象则保持扁平化,并入其父级的列中。属性名会被原样使用(加引号)—— 你的列名就是 schema 的属性名,仅在嵌套路径超出 PostgreSQL 可命名长度时才会被缩短。
该投影是确定性的——同一个模式始终映射到相同的表和列。属性名会原样成为列名(加引号);类型名会被转换为蛇形命名作为表名(VideoGame → video_game)。唯一的例外是长度:PostgreSQL 无法容纳超过 63 字节的标识符,因此深度嵌套的路径会缩短其父对象以适配(morphological_description_ → morpdesc_)——该对象的每一列都使用相同的前缀,可在链接前于模型标签页中查看和编辑。属性也可以完全去掉其前缀,以匹配你的数据库中已有的列(product_identifiers.stock_keeping_unit → sku)——即模型标签页中名称旁的链接开关。每个表都带有一个 _sync_revision 列,用于保持重放的收敛。
| 在你的模式中 | 在你的数据库中 |
|---|---|
| 带标识的对象(语义 ID 或键) | 拥有独立的表;数据库键成为唯一索引和 upsert 目标 |
| 标量字段(字符串、数字、布尔值) | 带类型的列(TEXT、BIGINT、NUMERIC、BOOLEAN) |
| 封闭集合(取值限定为某个列表的字段) | 普通的 TEXT 列——没有 CHECK,也没有数据库枚举类型。取值列表在 AI 作答时强制执行,因此之后向其中添加取值也不会迁移你的数据库。如需约束请自行添加——同步不会改动它 |
| 可空或非空字段 | 非空字段默认会成为 NOT NULL 列,并与下方的质量关卡配合使用——在最严格的关卡下,必填引用的外键也会带上 NOT NULL;关闭该强制约束(可在注册时关闭,也可稍后关闭:首次同步之后的变更会作为一次受保护的迁移进入信息流),即可让所有列保持可空,仅由关卡来保证完整性 |
| 多语言字段 | 用一个 JSONB 列存储所有语言 |
| 内嵌值对象(无标识) | 展开为带前缀的列(dimensions_width) |
| 值对象数组 | 以父级为键的子表,有序,删除时级联 |
实体数组 / $ref 关系 | 连接源行和目标行的联结表,保留顺序 |
键字段(identifying) | 用于快速查找的二级索引 |
| 查询形状索引(有序字段列表) | 每个已声明的形状对应一个多列索引,其列序与它所服务的列表页查询一致——分面和封闭集合在前,排序列或范围列在最后,并包含多语言字段(此类形状会按数据库已接收的每种语言各生成一次);由分类环节提出并附带理由,在“模型”标签页中整理,每个实体可有多个 |
| 搜索字段(索引意图) | 对搜索框按片段匹配的文本建立三元组索引(pg_trgm)——按语言分别建立,且在多语言列上不设上限;绝不用于下拉选项值,后者应改为放入查询形状索引(包括多语言字段——此类索引会按数据库已接收的每种语言各生成一次);在未安装该扩展的副本上会被跳过(空操作),直到数据库所有者安装为止 |
| 坐标对(纬度 + 经度) | 为该对建立单个空间索引(PostgreSQL 原生 GiST,无需扩展)—— 支持半径、最近邻和地图视口查询 |
| 区间对(起始 + 结束边界) | 为该对建立单个范围索引 —— 支持重叠查询以及“该日期生效的是哪个值”类查询 |
一个数据库可以同步多个 schema。在关联的多个 schema 中同名的 entity 类型会落入同一张表,按其数据库键合并——每个 schema 的 enrichment 只更新其自身的列,因此被两个 schema 完成 enrichment 的公司会成为同时携带两组列的一行 record。某个 schema 独有的类型只需添加各自的表,通过 feed 中的自动迁移增量交付——无需重新下载。
关联 schema 时,比对步骤会准确显示哪些表将被合并(及其键和新增的列)以及哪些是新表;共享某张表的 schema 会采用该表现有的数据库键,并显示出来供你审核。如果这些 schema 没有任何共享内容,该流程会转而建议使用专用数据库。取消关联 schema 绝不会改动你的数据库——已同步的表会保留。
取消关联 schema 或删除同步后,我们这一侧会遗留两样东西:不再有任何内容写入的已存储实体状态,以及 schema 所携带的数据库属性(database key、列类型、索引、归属)。两个确认都会提供移除它们的选项,且仅适用于完全不再关联任何数据库的 schema——仍在别处同步的 schema 会保留全部内容。schema 本身、它的 enrichment 记录及其成本永远不会受到影响。
已关联的 schema 拥有已发布契约:即你的扩充和数据库实际使用的版本。编辑 schema 只会改动工作副本——文案改动会自动生效,而结构性改动(新增字段、类型或键的变更)则要等到你按下发布才会生效。发布会预览确切的影响,并将相应的迁移送入增量数据流:新列以 ALTER TABLE 增量的形式送达,而较重的改动(新的数据库键、类型变更)会作为受保护的迁移在你自己的数据库上运行——如果数据阻止了这些迁移(缺失或重复的键值),数据流会暂停并给出确切的问题,等你修复后自动重试。
发布功能位于数据库的Model标签页(当 Schema 处于关联状态时,工作流编辑器会显示一个指向该处的横幅)。在发布之前,它会同时展示两方面:你的数据库当前所遵循的约定,以及你的工作副本将要更改的所有内容的差异。对某项编辑不满意?还原为已发布版本会恢复该约定——此操作可撤销,而你搁置的草稿在 24 小时内仍可恢复。
重新关联一个在未关联期间被编辑过的 schema 也是同样的方式:同步会记住你的数据库已有的内容,只发送差异,外加对期间写入的行进行快照刷新。永远无需手动 DROP。
同样的承诺也适用于我们自己的升级。当新版本改进 schema 到表的映射方式时,你的同步会自动迁移——增量式变更会自行进入数据源。如果某次升级会重新调整你已有的表结构,我们绝不会在未通知的情况下改动你的数据:投送会暂停,你的 Database Sync 页面会请你应用它,并先明确展示会发生哪些变更。
多语言 enrichment 在这里同样是一等公民:本地化的值会以承载 enrichment 每种语言的 JSONB 列形式呈现——{"en": "Headache", "fr": "Céphalée"}——因此一个数据库即可同时服务你的所有语言环境。可直接在查询中选择某种语言(name->>'fr'),并且 JSON delta 载荷也会携带同样以语言为键的对象。
每个数据库在注册时都要回答一个问题:当富化返回存在缺口——非空字段未被填充——时,应写入什么?三种答案构成一个梯度。什么都不写:任何位置(包括嵌套对象内部)出现一处缺口,该实体即被拒绝。写入实体,但不含其不完整的子对象(默认):实体自身的行必须完整,但残缺的子对象会被跳过并上报,而不会拖垮整次富化。全部写入:缺口以 NULL 落库,不拒绝任何内容——但实体状态采用后写覆盖,最新一次富化就是该行数据,因此后来的不完整运行会抹掉先前已填充的内容。两个严格档位的存在,正是为了防止这种抹除。
未通过校验关卡的增强结果仍会保存为记录,也仍会触发 record.created webhook——其中 database.saved 为 false——并准确告知缺少了哪些必填字段,因此不完整的数据绝不会悄无声息地消失。每个缺失字段还会标明模型是声明其未知,还是直接遗漏:前者需要更强的模型、网页搜索或源文档,后者则需检查 Schema 或输入。只有数据库键字段始终为必填:缺少键值的增强结果无论处于哪一档都会被拒绝。
在严格档位下,一个复选框可将同样的约定映射到你自己的数据库中:为每个始终存在的字段生成 NOT NULL 列。在最严格的档位下,必填引用的外键也会受到约束——任何准入的行都不会缺少它们。而在跳过不完整的子对象档位下,这些列会刻意保持可空:自身缺少某个值的列表项会被丢弃,目标不完整的共享一对一引用(例如没人知道启用年份的那座球场)会被分离——该目标既不会写入也不会更新,保存的行在此处不指向任何内容,也就恰好在这些外键列中写入 NULL。两种情况都会在富化响应中上报,而顶层字段的缺口始终会导致拒绝。首次同步之后再修改该策略也不会白费:它会作为一次受保护的迁移进入信息流,并针对数据库中已有的行进行校验。
第二道关卡用于捕获重复身份:当同一列表中的两个条目解析到相同的数据库键时——模型为两家不同的公司臆造了同一个 id,或者该键无法区分它们——只能存在一行,因此写入最后一个,先前的会被丢弃,与其他地方一样遵循“最后写入者获胜”规则。每次冲突都会连同两个条目的标识值和一个判定一起报告:重复表示重复了相同的值,未丢失任何内容;冲突丢弃则丢失了其列出的值——要么是模型以带噪声的方式重复了同一事物,要么它们本就是不同的事物,此时键需要一个区分性属性(地区、年份、版本)。该列表会保存在记录上,因此即使响应早已消失,部分写入仍能说明丢失了什么。
在重新扩充之前需要了解一点:对于隶属于父级的列表,最新一次扩充的列表即为最终列表。若最新的答案未再次包含某个子行,该子行就会从你的数据库中删除——这正是真正的删除项传达给你的方式,而响应并不会报告这一点。当列表是模型凭记忆回想而非逐项枚举得出时,这一点尤为重要:对某元素的同位素或某人的获奖情况询问两次,第二次的答案可能更短,从而删掉原本真实存在的行。如果你需要每次运行结果的并集,请自行保留历史记录。
富集结果会自行进入已关联的数据库。其余的一切——在您修复架构之前被闸门拒绝的结果、您有意排除在外的运行,或想先审阅或更正的输出——都通过向数据库发送记录完成:在历史记录页面选择它们,或从工作流调用 API。
往返流程。 关闭数据库同步进行富集,在您自己的工作流中重塑或审批结果,然后发送。您发送的内容会依据该架构已发布的契约重新校验,并经过与富集相同的准入闸门——注入永远无法写入富集所不能写入的内容。
有两点值得了解。原样发送一条记录时,它会存储在该记录名下。发送修改后的输出则会创建一条指向原记录的新记录,因为记录是一份审计轨迹:它们绝不会在引用它们的数据之下发生变化,因此您数据库中的内容始终可追溯到一条恰好包含这些值的记录。此外,校验使用的是当前的契约 — 如果记录生成之后架构已发生变化,历史记录页面会在您发送前作出提示。
历史记录页面还会按记录显示其是否已进入数据库:已发送、部分发送,或被拒绝并附上原因。可通过 Web 应用、API、MCP、n8n 和 Make 使用。
该数据流是每个数据库独立的严格 FIFO 队列:获取一个窗口(可选启用租约,这样崩溃的工作进程的批次会先于更新的数据重新投递)、应用、确认。Webhook 通知经过防抖处理——每条新增量都会重置静默期计时器,因此一批密集的扩充只会通知一次;可配置的最大延迟为等待时间设定上限,而当获取页面写满时会立即触发通知。两个清除选项控制 Entity Enricher 保留的内容:在确认后删除已投递的增量副本;以及——出于数据最小化考虑——在与该 schema 关联的每个数据库都已接收后,删除实体状态本身。两者均可设置以天为单位的可选延迟:已投递的副本会在确认后继续保留该时长(即重放窗口),已投递的实体则会保留到其在该时长内始终没有更新为止,每小时运行的清除任务会删除已过期的内容。请注意,状态清除是最小化而非彻底擦除:扩充记录在你删除之前会一直保留,同时该操作会对已清除的实体停用跨扩充合并。
按表的校验和端点让你随时验证副本是否已收敛,无需重新下载任何内容。
所有功能都集中在应用中的一个位置 —— 侧边栏「历史」正下方的 Database Sync:为任意模式注册数据库(含数据库密钥审核)、关联或取消关联模式、用开关暂停某个已关联模式的富化数据推送(在重新启用前不会有新数据或通知 —— 模式发布仍会推送其 DDL,而暂停期间运行的富化只能通过重新拉取快照才能到达副本)、编辑其选项、查看 webhook 端点并显示其签名密钥、下载快照、浏览当前实体状态、查看待处理的增量队列(只读 —— 绝不会改动你工作流的游标),以及查看所生成数据表及其键和联结表的实体关系图。在多数据库同步中,该图可以聚焦于单个模式:由其他模式提供的表、列和关联会变灰 —— 仍原位可见 —— 让你清楚看到每个模式对共享表的贡献。
当多个数据库落在同一台机器上时,工具栏的同步主机按钮免去了逐个数据库配对的繁琐流程:只需为该机器配对一次,然后把注册项分配给它。主机会认领每一项,在物理数据库不存在时创建它,并开始同步——于是注册数据库变成你在这里做的一个决定,而不是服务器上的一次终端会话。配对以每个 Entity Enricher 服务器为单位,因此一台机器可以并行服务多个实例。
被你的数据库拒绝的语句——通常是新建唯一索引下已存在的重复数据——不会卡住排在其后的队列。该次富集的批次会被隔离,数据流继续流动,同时该批次会连同被数据库拒绝的语句一起列在隔离区标签页中。排除原因后重新注入——这会依据实体的当前状态重新投影,而不是重放过期的语句——或者直接丢弃。
GET /api/databases//changes?since=…&format=sql,然后 POST /api/databases//ack。正在使用 Supabase?我们的 Supabase MCP 对比通过 JSON 和简单的表结构图,展示 EE 的关系与同步规则如何保护产品目录。
同步过程中没有任何环节会运行在你的数据库服务器上——上述每条路径都是一个出站消费者,连接到你提供的任意 DSN。Azure Database for PostgreSQL、OVHcloud、AWS RDS、Supabase 或任何其他托管实例,其工作方式与自托管实例完全相同:将消费者指向云 DSN(托管服务商通常强制使用 TLS,因此需添加 sslmode=require)并应用即可。
--dsn 指向托管实例即可。delta_available webhook 唤醒 Azure Function / AWS Lambda / OVHcloud 函数,由它拉取 REST 数据源、执行 SQL 并进行确认。两条规则可确保任何自行实现的消费者安全:在单个事务中按顺序执行每个批次的语句,并仅在提交之后进行确认。增量具有幂等性并受修订版本保护,因此在确认之前崩溃只意味着该批次会被重新投递,重新应用最终会收敛一致。
数据库功能面向付费套餐开放(可注册的数据库数量由套餐决定)。首发支持的方言为 PostgreSQL;每个数据库都需声明自己的方言,MySQL / MariaDB、SQL Server 和 Oracle 正在规划中。