核心概念
Graph 模块面向图数据和图数据库。它与 MySQL 等关系型数据库一样,都可以保存结构化数据、属性和索引,也都支持查询、更新、删除和事务;但两者组织数据和表达关联的方式不同。
理解 Graph 模块最重要的第一步,是区分“关系型数据库中的关系”和“图数据库中的关联”:
- 关系型数据库以表、行、列和外键为核心,实体之间的关联通常通过外键和 JOIN 表达;
- 图数据库以节点、边和路径为核心,实体之间的关联本身就是可以保存属性、被查询和继续遍历的数据。
MySQL 与图数据库的整体对照
下面的映射用于帮助理解概念,不表示两种数据库的实现完全等价:
| 业务概念 | MySQL 关系型数据库 | 图数据库 | 主要差异 |
|---|---|---|---|
| 数据隔离单元 | Database / Schema | Graph Space | 都可以用于租户、项目或环境隔离;Space 还承载图数据和图结构 |
| 实体类型 | Table | Label / Tag / Node Type | 图数据库允许不同类型的实体通过边直接连接 |
| 实体记录 | Row | Node | 节点有稳定 ID、标签和属性 |
| 实体属性 | Column | Node Property | 属性附着在节点或边上,类型由 Schema 约束 |
| 实体唯一标识 | Primary Key | Node ID | 节点 ID 是更新、删除、幂等写入和实体归一的基础 |
| 实体关联 | Foreign Key | Edge | 边本身是数据,可以有类型、方向、属性和唯一身份 |
| 多对多关联 | Junction Table | 多条 Edge | 不需要先创建中间表,再通过两次 JOIN 还原关联 |
| 关联属性 | Junction Table 的列 | Edge Property | 例如 since、weight、role 直接属于这条边 |
| 多级关联查询 | 多次 JOIN、子查询或递归逻辑 | Path / Traversal | 查询可以沿边连续遍历节点和关系 |
| 查询语言 | SQL | Graph SDK 查询语言、Cypher、nGQL | Graph SDK 提供跨后端的统一语义,也支持原生方言 |
| 结构定义 | DDL、表结构和外键 | Schema、节点类型、边类型和索引 | 图结构通常更适合表达关联网络和持续演进的关系 |
例如,在电商场景中,MySQL 可能使用 user、order、product 和 order_item 四张表,通过多个外键和 JOIN 查询“用户买过哪些商品”。图数据库则可以直接保存:
(用户)-[下单]->(订单)-[包含]->(商品)如果还需要表达“用户关注了商品”“商品属于某个分类”“用户与另一个用户共享设备”,只需要增加相应的节点和边类型,而不必为每一种关联都设计新的中间表和 JOIN 组合。
图数据库的基本组成
Graph Space:图数据空间
Graph Space 是 Graph SDK 中用于隔离图数据和图结构的逻辑空间,可以类比 MySQL 中的 Database,但不应简单理解为一个普通表集合。
一个 Space 通常包含:
- 节点和边数据;
- 节点类型、边类型和属性定义;
- 索引等查询结构;
- 与该空间相关的导入、查询和生命周期操作。
常见的 Space 划分方式包括:
- 每个租户一个 Space;
- 每个知识库一个 Space;
- 开发、测试、生产分别使用不同 Space;
- 不同业务域或项目使用不同 Space。
Neo4j 通常将 Space 映射为 database,Nebula 通常将其映射为 Space。不同后端对创建、删除、动态切换和权限的支持可能不同,应用应通过能力检查和真实环境验证确认行为。
Node:节点
节点表示一个可以独立识别的业务实体,例如用户、人物、公司、设备、商品、文档、地点或事件。
节点通常包含:
- 稳定 ID:由业务侧生成或映射,不能随着导入批次变化;
- 标签或类型:说明节点属于什么实体类别;
- 属性:保存名称、状态、时间、数值等业务信息。
与 MySQL 的行类似,节点保存一组属性;但节点不只是某张表中的一行,它还可以通过多种边连接到其他类型的节点。
稳定 ID 对图谱尤其重要,因为同一实体可能在多份文件、多个批次或多次抽取中重复出现。只有稳定 ID 和实体归一规则明确,才能实现幂等更新、去重、删除、增量导入和来源追踪。
Label、Tag 和 Node Type:节点类型
节点类型用于描述节点的业务类别。不同图数据库对术语的叫法不同:Neo4j 常用 Label,Nebula 常用 Tag,Graph SDK 使用节点类型和标签表达公共语义。
例如:
Person、Company、Document、Product、Event一个节点可以拥有多个标签时,可以表达“某人同时是员工和作者”这类复合分类;但为了跨 Neo4j 和 Nebula 保持一致,公共模型通常应优先使用一个清晰的主类型,并在属性或边中表达其他业务分类。
节点类型不是完整的业务对象模型。业务对象可能跨越多个节点类型,也可能需要额外的版本、来源、权限和生命周期信息。
Edge:边
边表示两个节点之间的业务关联,例如:
(Person)-[WORKS_FOR]->(Company)
(User)-[PURCHASED]->(Product)
(Document)-[MENTIONS]->(Person)边通常包含:
- 起点和终点:说明关联连接了哪些节点;
- 边类型:说明是什么关联;
- 方向:例如
A -> B和B -> A可能表示不同含义; - 属性:例如关系发生时间、权重、角色、来源和置信度;
- rank 或序号:在后端允许同一对节点存在多条同类型边时,用于区分平行边。
边不是 MySQL 中的简单外键。外键只保存引用约束,而边本身可以被查询、过滤、统计、排序和继续遍历,也可以携带自己的属性。
Property:节点和边的属性
属性用于描述节点或边的具体信息,例如 name、status、createdAt、weight 和 confidence。
与 MySQL 列类似,属性通常具有类型约束。Graph SDK 的公共属性类型包括字符串、布尔值、整数、浮点数、日期和日期时间等。属性设计时需要注意:
- 经常用于过滤、排序和关联定位的字段应考虑建立索引;
- 不要把大量不稳定、难以查询的结构全部塞进一个属性 Map;
- 需要表达业务关联的内容优先考虑建模为边,而不是在节点中保存一串 ID;
- 日期、列表、Map 等复杂值需要在目标图数据库中进行真实环境验证。
Schema:图结构契约
MySQL 的表结构通常描述表、列、主键、外键和索引。Graph SDK 的 Schema 描述:
- 节点类型及其属性;
- 边类型及其属性;
- 属性类型和是否必填;
- 节点或边上的索引;
- 部分后端可以支持的约束和元数据。
Schema 是应用声明与数据库实际结构之间的契约,不等同于完整的业务领域模型。它回答的是“数据库允许保存和查询什么”,而不是“业务流程应该如何运行”。
图谱项目通常需要在首次导入前建立 Schema,并在后续版本中以迁移方式演进。新增兼容属性通常可以增量应用;删除属性、改变类型或删除索引等破坏性操作,则应由上层执行权限确认、审批和备份。
不同图数据库对 Schema 的支持并不完全一致。例如 Nebula 的属性过滤通常要求相应索引已经创建并完成重建,Neo4j 与 Nebula 对多标签、边端点约束和唯一索引的支持也存在差异。Graph SDK 通过能力矩阵和 Schema 反查结果暴露这些差异。
Path 和 Traversal:图查询的核心思维
在 MySQL 中,开发者通常从“查询哪张表”开始,再思考需要几次 JOIN;在图数据库中,开发者通常从“从哪个节点出发、沿什么边走、要走几跳”开始。
例如:
- 查找用户购买过的商品:
User -> PURCHASED -> Product; - 查找员工所在公司的所在行业:
Employee -> WORKS_FOR -> Company -> IN_INDUSTRY -> Industry; - 查找文档提到的人物之间是否存在共同组织:从文档沿
MENTIONS和MEMBER_OF进行多跳遍历。
Path 是一次或多次边连接形成的路径,Traversal 是沿路径进行的遍历过程。查询通常会同时描述:
- 起始节点类型和过滤条件;
- 边类型、方向和跳数;
- 目标节点类型和过滤条件;
- 返回节点、边、完整路径或聚合结果;
- 排序、分页和结果数量限制。
图数据库并不是所有查询都比 MySQL 更快。单表过滤、简单聚合和强事务报表通常仍适合关系型数据库;图数据库的优势主要体现在关系密集、多跳遍历、路径分析和关联解释上。
Graph SDK 中的查询概念
Graph SDK 提供两种查询方式:
Portable Query:统一查询
Portable Query 表达 Neo4j、Nebula 等后端可以共同理解的查询语义,包括节点和边模式、方向、过滤、投影、路径、聚合、排序、分页以及部分 UNION 和 OPTIONAL MATCH 能力。
它可以通过程序化模型构建,也可以使用 Graph SDK 自己定义的字符串查询语言。字符串查询会先解析为统一语义,再由目标后端编译为参数化 Cypher 或 nGQL。
Native Query:原生查询
Native Query 直接使用后端原生语句,例如 Neo4j 的 Cypher 或 Nebula 的 nGQL。它适合:
- 最短路径和路径算法;
- 数据库专属函数和优化提示;
- 管理语句和复杂子查询;
- Portable Query 尚未覆盖的高级能力。
Native Query 会绑定具体后端,不能假设同一段语句可以在 Neo4j 和 Nebula 之间复用。应用应把原生查询限制在明确的后端边界内。
GraphStore:SDK 的运行入口
GraphStore 是一个已配置的 Graph SDK 运行实例,可以理解为“一个后端连接配置及其运行资源的统一入口”,而不是 MySQL 中的 Database,也不是每次请求都临时创建的对象。
GraphStore 通常组合以下能力:
| 需求 | SDK 能力 |
|---|---|
| Space、Schema 和索引管理 | Manager |
| 节点和边写入 | Writer |
| Portable / Native 查询 | Query Executor |
| 显式事务 | Transaction |
| 批量和异步导入 | Import |
| 连接探活和能力检查 | Health / Capability |
在高并发应用中,GraphStore、Driver 和连接池通常由应用容器长期复用;请求级对象只保存本次查询或写入的参数。应用关闭时,再由生命周期管理者统一释放连接、任务执行器和游标等资源。
控制面与数据面
可以用两个视角理解 Graph SDK 的职责:
- 控制面:创建和选择 Space,应用和检查 Schema,创建索引,读取能力矩阵,检查健康状态;
- 数据面:写入和删除节点、边,批量导入,执行查询,读取路径和结果,使用事务。
这个划分与 MySQL 中“数据库管理和表结构管理”与“业务 SQL 读写”类似,但图数据库还需要额外管理边类型、路径查询能力和后端图特性。
Capability:后端能力差异
Neo4j 和 Nebula 都是图数据库,但并不意味着它们支持完全相同的操作。Capability 描述某个后端在当前版本和配置下是否支持某项功能,例如事务、流式游标、唯一索引、多标签、聚合分组、变长路径、单查询超时或 Schema 反查。
应用可以利用能力信息:
- 在自己的 UI 中隐藏或标记不支持的操作;
- 在运行前选择 Portable 或 Native Query;
- 在迁移前展示风险和警告;
- 在多后端部署时避免把某一后端的特性误认为公共能力。
当功能无法保持统一语义时,Graph SDK 应明确返回能力异常,而不是静默改写查询或退化成不可控的全图扫描。
如何选择关系型数据库或图数据库
两类数据库不是相互替代的关系,常见选择可以参考以下原则:
| 主要问题 | 更适合的方案 |
|---|---|
| 订单、库存、财务明细、固定报表和强一致事务 | MySQL 等关系型数据库 |
| 多跳关系、路径、网络结构和关联探索 | 图数据库 |
| 大量简单键值查询和缓存 | KV 数据库或缓存系统 |
| 文档全文检索和相关性排序 | 搜索引擎或文档数据库 |
| 既要保存交易事实,又要分析复杂关系 | 关系型数据库与图数据库组合 |
在组合架构中,关系型数据库可以作为业务事实和交易系统,图数据库保存用于关联分析、知识检索或路径查询的投影。两者之间需要由上层数据同步、事件流或批处理流程保证数据更新策略,Graph SDK 不自动替代业务系统的主数据管理。
从 MySQL 思维迁移到图思维
从关系型数据库迁移到图数据库时,可以按以下步骤转换:
- 先识别业务实体,把稳定、可独立识别的对象设计为节点;
- 再识别实体之间需要查询、过滤或解释的关联,把它们设计为边;
- 把关联本身的时间、角色、权重、来源和置信度放到边属性中;
- 为节点和边设计稳定 ID,保证重复导入和实体归一;
- 把频繁的 JOIN 链路改写成起点、边方向、跳数和过滤条件;
- 保留适合报表和交易处理的关系型模型,不要为了使用图数据库而强行迁移所有数据;
- 使用真实数据验证索引、查询计划、事务和后端能力,而不是只根据概念模型判断性能。
Graph 数据建模的重点不是把每一张 MySQL 表机械地转换成节点,而是识别业务中真正需要被遍历、解释和持续维护的关联网络。