在Postgres里直接写图数据:pgGraph GQL映射写入CREATE、MERGE与DELETE全解析
在Postgres里直接写图数据pgGraph GQL映射写入CREATE、MERGE与DELETE全解析 前言为什么要在 Postgres 里直接写图数据pgGraph 是一个开源的 PostgreSQL 扩展graph database extension它直接运行在你现有的 Postgres 数据之上表仍然是数据源source of truthpgGraph 从普通表中构建可重建的图索引让你用graphschema 下的函数做图查询——遍历、最短路径、关系检索。更关键的是它还提供了一组受控的 GQL 写入能力CREATE、SET、REMOVE、DELETE、DETACH DELETE和MERGE让你在图查询语句里直接写回映射的 PostgreSQL 表而不必切换工具或搬动数据。本文将用尽量少的代码完整解析这三个最常用的写入操作CREATE向已注册的源表插入一个节点或一条有向关系MERGE基于主键身份的存在则更新、不存在则插入的幂等 upsertDELETE / DETACH DELETE删除关系行或连同关联边一起删除节点。官方支持的 GQL 写入能力清单见 release/v1-gql-profile.json人类可读版本在 docs/user_guide/gql-profile.mdx。 前提开启 mutable 写入模式pgGraph 的图投影默认是只读的csr_readonly模式。所有 GQL 写入都要求满足两个条件详见 docs/user_guide/configuration.mdx以mode : mutable_overlay构建图开启 GUCgraph.mutable_enabled on。SET graph.mutable_enabled on; SELECT * FROM graph.build(mode : mutable_overlay);写入通过graph.gql()函数执行签名为graph.gql(query text, params jsonb, hydrate boolean)每行结果是一个 JSONB 对象。参数用 JSONB 传入语法上与 Cypher 非常相似。另外一个关键前提表和关系必须注册到图目录。用graph.add_table()注册节点表含主键列用graph.add_edge()注册边表步骤见 docs/user_guide/schema-registration.mdx。➕ CREATE插入节点与有向关系CREATE的映射语义是一次只写一行创建节点向注册过的节点源表插入一行例如CREATE (c:customers {id: $id, name: $name})创建关系先锁定 MATCH 命中的源端点与目标端点然后向注册过的边行表插入恰好一条边例如CREATE (a)-[r:purchased {id: $purchase_id}]-(b)。SELECT row FROM graph.gql( MATCH (a:customers {id: $from}), (b:products {id: $to}) CREATE (a)-[r:purchased {id: $purchase_id}]-(b) RETURN r, params : {from:c-42,to:p-9,purchase_id:e-77}::jsonb );几个值得新手记住的行为细节标签label就是注册表名关系类型就是注册的边标签不存在凭空建图新插入的边会写入事务本地的 overlay同一个事务内后续查询就能看到这条新边并发动用同一个主键CREATE时遵循 PostgreSQL 唯一约束一个事务提交成功另一个收到 SQLSTATE23505unique violation不会出现重复行。 MERGE幂等的存在即更新、缺失则插入MERGE是 pgGraph 中非常实用的 upsert 语义。语法形如MERGE (n:label {properties}) [ON CREATE SET ...] [ON MATCH SET ...] RETURN ...行为要点来源docs/user_guide/api-reference.mdx 的 GQL 章节身份判定以注册的主键列作为匹配身份配置了租户作用域时租户身份也会参与分支互斥ON CREATE SET只对新插入的行求值ON MATCH SET只对命中已有行的情况求值并发收敛插入竞争使用 PostgreSQL 的ON CONFLICT DO NOTHING多个会话抢同一个主键时最终收敛到同一行源表数据只有当ON MATCH SET真的可能更新时才会对已命中行加FOR UPDATE锁权限最小化MERGE需要源表的SELECTINSERT权限只有包含ON MATCH SET时才额外需要UPDATE权限。SELECT row FROM graph.gql( MERGE (c:customers {id: $id, name: $name}) ON CREATE SET c.status new ON MATCH SET c.last_seen_at $seen_at RETURN c.id AS customer_id, c.status AS status, params : {id:c-42,name:Ava,seen_at:2026-05-31T12:00:00Z}::jsonb );对需要打卡式记录每次调用都可能新增也可能只是刷新的场景这种幂等写法比先查后插要安全得多——并发竞态由数据库层兜底。️ DELETE 与 DETACH DELETE精准删除关系与节点关系DELETE用于删除一条有向关系行SELECT row FROM graph.gql( MATCH (a:customers {id: $from})-[r:purchased]-(b:products {id: $to}) DELETE r RETURN a.id AS customer_id, b.id AS product_id, params : {from:c-42,to:p-9}::jsonb );只有当 PostgreSQL 恰好删除了一条边行时pgGraph 才会在当前后端里给对应的图边打 tombstone端点节点不会被动端点与关系类型标签可以省略但前提是通配模式只能解析到唯一的静态标签边映射并发的双删遵循 PostgreSQL 语义一个事务删成功另一个因行已失效收到 SQLSTATE22000。DETACH DELETE用于删除节点及其全部关联的边先删正向与反向边行再删节点行。任何一步失败整个语句回滚源表数据保持权威状态。注意它拒绝删除那些没有注册边行表的关联关系——因为 pgGraph 没有安全的通用策略去改写任意端点表的外键。SELECT row FROM graph.gql( MATCH (c:customers {id: $id}) DETACH DELETE c RETURN c.id AS customer_id, params : {id:c-42}::jsonb );️ PostgreSQL-first事务、并发与权限pgGraph 的 GQL 写入是PostgreSQL-first文档原文表述的这是理解其安全模型的关键先写源表所有 INSERT/UPDATE/DELETE 都通过 SPI 落到映射的 Postgres 表上PostgreSQL 负责执行权限ACL、约束、RLS、触发器和 MVCC写后重读DML 与触发器执行完后pgGraph 会重读被影响的源行如果触发器副作用改了主键、租户身份或关系标签写入会被拒绝并回滚防止源身份与图坐标分叉写前复核SET、REMOVE、DELETE、DETACH DELETE在最终写入边界会锁定命中的源行并重新检查 GQL 谓词——如果另一事务已把数据改成不匹配语句会失败而不是覆盖并发修改SQLSTATE22000完全参与 Postgres 事务机制savepoint、PL 子事务都受支持回滚 savepoint 会恢复其之前的事务本地图 overlay 状态。⚠️ 能力边界知道不支持什么同样重要写入范围故意保持窄一次只写一行一个节点、一条边、一个属性多行批量图写入不在此版本 GQL 子集内在csr_readonly投影上CREATE、SET、REMOVE、DELETE、DETACH DELETE、MERGE全部被拒绝批量导数的正确姿势直接用集合式 DML 写已注册的 Postgres 源表提交后调用一次graph.apply_sync()既保留 PostgreSQL 的完整约束体系又能走增量 mutable overlay 同步每次 GQL 写入调用接受一个参数对象大批量场景请避免逐行调用循环见 docs/known-issues.mdx 的说明。 延伸阅读内容路径GQL 查询与写入完整说明docs/user_guide/querying.mdxgraph.gql()API 参考docs/user_guide/api-reference.mdx1.0 版 GQL 能力清单自动生成docs/user_guide/gql-profile.mdxmutable 相关配置项docs/user_guide/configuration.mdxGQL 写入行为集成测试graph/src/pg_tests/gql.rs表/边注册指南docs/user_guide/schema-registration.mdx✅ 小结pgGraph 让你不用离开 Postgres就能写图数据CREATE提供精确到单行的节点与关系插入MERGE提供并发安全的幂等 upsertDELETE/DETACH DELETE提供带谓词复核的精准删除。所有写入都遵循 PostgreSQL-first 原则——表始终是权威数据源图索引只是可随时重建的派生状态。对于既想保留关系型运维体系、又想获得图能力的团队这套映射写入模型是低风险、可审计的入门路径。创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考