从三元组到可查询图谱:手写知识图谱构建的最小步骤
知识图谱构建不是先选数据库再想数据,而是先把一个能回答的业务问题拆成实体和关系,再准备成三元组或表格形式。
本文用“公司-人物任职”这个最小场景,演示从零到能在 Neo4j 里查出结果,适合第一次动手建图谱的读者。
如果你还没有明确的查询目标,建议先停下来把问题写清楚,否则导入的数据很难验证对错。
先确定图谱要回答什么问题
动手前先写下一句业务问题,例如“查某个人在哪些公司担任什么职位”。
这句话决定了实体类型和关系类型:人物、公司是实体,任职是关系,职位可以作为关系的属性。
没有这一步,导入后很容易发现数据无法支撑查询。
准备阶段只需要三样东西:
- 一个明确的查询目标,例如按人名查公司或按公司查任职人员。
- 实体和关系的清单,每个实体给唯一标识,例如
person_id和company_id。 - 可运行的图数据库环境,本文以 Neo4j 为例,本地或测试环境均可,不建议直接在生产实例上试导入。
如果数据量很小,可以先用 CSV 或手工三元组文件,不必一开始就做复杂的抽取流水线。
把数据整理成可导入的三元组
知识图谱常见的最小表示是三元组:头实体、关系、尾实体。
以任职场景为例,可以准备两个 CSV 文件,一个放节点,一个放关系。
节点文件建议包含唯一 ID 和用于展示的名称:
id,label,name
p1,Person,张三
c1,Company,示例科技
关系文件用起点 ID、终点 ID 和关系类型:
from_id,to_id,type,role
p1,c1,WORKS_AT,技术总监
这里的关键是 ID 必须唯一且稳定,不要用名称当唯一键,否则重名或改名会导致重复节点。
关系类型建议用大写英文,属性名用小写英文或下划线,避免空格和中文标点,减少导入时的转义问题。
在 Neo4j 中导入并建立约束
导入前先给节点 ID 建唯一约束,这是最容易被跳过但最值得做的一步。
在 Neo4j Browser 中执行:
CREATE CONSTRAINT person_id_unique IF NOT EXISTS
FOR (p:Person) REQUIRE p.id IS UNIQUE;
CREATE CONSTRAINT company_id_unique IF NOT EXISTS
FOR (c:Company) REQUIRE c.id IS UNIQUE;
如果使用 Neo4j 5 及以上版本,IF NOT EXISTS 可以避免重复执行报错;
旧版本若不支持该子句,去掉后手动确认约束不存在即可。
接着用 LOAD CSV 导入节点,文件路径需要放在 Neo4j 允许的导入目录下,常见为 import 目录:
LOAD CSV WITH HEADERS FROM 'file:///nodes.csv' AS row
MERGE (n:Person {id: row.id})
SET n.name = row.name;
上面示例只处理人物节点,公司节点可复制一份把标签改为 Company。
导入关系时先匹配两端节点,再创建关系:
LOAD CSV WITH HEADERS FROM 'file:///relations.csv' AS row
MATCH (a:Person {id: row.from_id})
MATCH (b:Company {id: row.to_id})
MERGE (a)-[r:WORKS_AT]->(b)
SET r.role = row.role;
如果关系文件里混有多种起点类型,需要按类型拆文件或加类型字段分别处理,不要用一个 MATCH 硬套所有情况。
导入时容易踩的坑
最常见的失败是路径错误,LOAD CSV 报找不到文件时,先确认文件是否在数据库的 import 目录,以及路径是否用了 file:/// 前缀。
第二个坑是 CSV 编码和表头空格,表头带空格会导致字段名匹配不上,导入前用文本编辑器确认没有多余空格。
关系重复也值得注意:如果反复执行同一条导入语句,CREATE 会产生重复关系,而 MERGE 在匹配条件正确时不会。
建议关系和节点都用 MERGE,并配合唯一约束。
另一个边界是空值,CSV 中缺失的 ID 会让 MATCH 失败,导入前先过滤掉空 ID 行。
用一条查询验证图谱是否可用
导入完成后不要只看节点数量,直接跑目标查询:“查张三在哪些公司任职”。
MATCH (p:Person {name: '张三'})-[r:WORKS_AT]->(c:Company)
RETURN p.name, c.name, r.role;
返回结果包含人物、公司和职位,说明节点、关系和属性都已正确落库。
再反向查一次公司:
MATCH (c:Company {name: '示例科技'})<-[r:WORKS_AT]-(p:Person)
RETURN p.name, r.role;
两次查询都能返回预期结果,才算完成最小验证。
如果结果为空,优先检查 ID 是否一致、关系方向是否写反、CSV 是否真的被读取。
常见疑问
一定要用 Neo4j 吗? 不一定。
数据量小、查询简单时,关系型数据库加关联表也能实现;
需要多跳关系查询时图数据库更自然。
选型要看查询模式,不是看名词热度。
三元组和 CSV 是什么关系? 三元组是数据模型,CSV 只是承载三元组的文件格式之一。
你也可以用 JSON、数据库表或直接写 Cypher 创建语句,核心仍是实体、关系、属性的定义。
图谱建好后怎么更新? 用稳定 ID 做 MERGE,新增数据重复执行导入语句即可;
删除或改关系要单独写语句,并先备份或在小数据集上验证,避免误删。
到这里,一个可查询的最小知识图谱已经跑通。
后续扩展时,优先增加实体类型和关系类型,而不是急着堆数据量;
每加一类关系,都用一条真实查询验证它是否被正确使用。