用 CSV 导入 Neo4j 知识图谱并验证查询结果

知识图谱配置在 Neo4j 里主要做三件事:定义节点和关系的数据结构、把数据导入图数据库、用 Cypher 查询验证结果。
如果数据还停留在 CSV 或表格阶段,先别急着写导入语句,把实体类型和关系方向确定下来,后面会省很多返工。

先确定图谱结构再动手导入

Neo4j 用节点表示实体,用关系表示实体之间的连接。
配置前先回答两个问题:哪些字段是实体,实体之间是什么关系。
比如“用户购买商品”可以拆成 User 节点和 Product 节点,关系类型为 BOUGHT,方向从用户指向商品。

建议在纸上或表格里列出:

  • 节点标签:如 User、Product、Category
  • 每个节点的唯一标识:如 user_id、product_id
  • 关系类型和方向:如 (:User)-[:BOUGHT]->(:Product)
  • 关系上是否需要属性:如购买时间、数量

结构确定后,准备两类 CSV 文件:节点文件和关系文件。
节点文件每行一个实体,关系文件每行一条连接,并用 ID 字段关联两端节点。

准备 CSV 数据文件

假设要导入用户和商品数据,可以准备两个文件。

users.csv:

user_id,name,city
u001,张三,北京
u002,李四,上海

products.csv:

product_id,title,price
p001,机械键盘,299
p002,显示器,1299

bought.csv:

user_id,product_id,buy_date
u001,p001,2025-01-10
u002,p002,2025-01-12

把文件放到 Neo4j 的 import 目录下,这是 LOAD CSV 默认能读取的位置。
如果使用 Docker 部署,确认启动时挂载了该目录;
如果使用桌面版,可以在设置里查看 import 路径。

用 Cypher 导入节点和关系

先导入节点。
下面的语句会为每一行创建或更新一个 User 节点,并用 user_id 作为唯一标识:

LOAD CSV WITH HEADERS FROM 'file:///users.csv' AS row
MERGE (u:User {user_id: row.user_id})
SET u.name = row.name, u.city = row.city;

同理导入商品节点:

LOAD CSV WITH HEADERS FROM 'file:///products.csv' AS row
MERGE (p:Product {product_id: row.product_id})
SET p.title = row.title, p.price = toFloat(row.price);

再导入关系。
关系文件里只有两端 ID 和关系属性,需要先匹配已存在的节点,再创建关系:

LOAD CSV WITH HEADERS FROM 'file:///bought.csv' AS row
MATCH (u:User {user_id: row.user_id})
MATCH (p:Product {product_id: row.product_id})
MERGE (u)-[r:BOUGHT {buy_date: row.buy_date}]->(p);

执行后如果返回类似 Added 2 nodes, created 2 relationships 的提示,说明导入有结果。
如果返回 0 行,先检查 CSV 路径和字段名是否和语句一致。

容易踩坑的几个地方

CSV 路径写错:file:/// 后面跟的是 import 目录内的相对路径,不是系统绝对路径。
报错 Couldn't load the external resource 时,优先确认文件名和目录。

字段名大小写不一致:Cypher 里 row.user_id 必须和 CSV 表头完全一致,表头有空格或大小写不同都会取不到值。

关系导入前节点不存在:MATCH 找不到节点时不会创建关系,也不会报错。
可以在关系导入前先跑 MATCH (u:User) RETURN count(u); 确认节点数量。

重复导入产生重复关系:使用 MERGE 而不是 CREATE 可以避免重复创建,但关系属性参与匹配时,属性值不同仍会新建关系。
导入前想清楚哪些属性应该放在关系上。

验证图谱是否配置成功

导入后不要只看语句执行成功,用查询确认数据能按预期返回。
查某个用户买过哪些商品:

MATCH (u:User {user_id: 'u001'})-[:BOUGHT]->(p:Product)
RETURN u.name, p.title, p.price;

查所有关系数量:

MATCH ()-[r]->() RETURN type(r), count(r);

如果数据量会持续增长,建议在唯一标识字段上建约束,避免重复节点:

CREATE CONSTRAINT user_id_unique IF NOT EXISTS
FOR (u:User) REQUIRE u.user_id IS UNIQUE;

建约束后再执行导入语句,重复数据会被拦截或合并,比事后清理更省事。

常见疑问

导入时提示内存不足怎么办?

LOAD CSV 默认会分批处理,但大文件仍可能占用较多内存。
可以先用 LIMIT 试跑前 100 行,确认语句正确后再去掉限制。
也可以在 neo4j.conf 中调整事务内存相关参数,但改配置前先备份原文件。

CSV 里的空值怎么处理?

空字符串会被当成空值写入属性。
如果某个字段允许为空,导入语句里可以加条件判断,例如 SET u.city = row.city 前先确认 row.city 不为空,避免把空字符串覆盖到已有数据上。

导入后查询很慢,先查什么?

先用 PROFILE 查看执行计划,确认查询是否走了索引。
如果按 user_id 查询,却没有在 User.user_id 上建索引或约束,Neo4j 会扫描全部节点。
建约束后重新执行查询,观察扫描节点数是否下降。

Neo4j 知识图谱配置的关键不是把语句跑通一次,而是让节点唯一、关系方向明确、查询能稳定返回结果。
按“定结构、备 CSV、导节点、导关系、查结果”的顺序操作,大部分导入问题都能在验证阶段暴露出来。

分享到:
上一篇
关系抽取配置怎么配?从schema定义到批量入库的实操流程
下一篇
用 pdftotext 和 Python 把 PDF 批量转成可检索文本的配置方法
1
系统公告

关于香港云优质服务器IP地址更换的通知

尊敬的客户: 因原IP运营商大幅涨价,为避免成本转嫁至用户,我司决定更换IP服务商。本次更换后,您的续费价格将保持不变,且新IP网络质量与服务标准不受影响。新IP已分配至后台,即刻生效(更换的新IP都是香港原生IPv4)。 涉及 IP 段: 45.192.x.x 旧 IP 停用时间: 2026 年 12 月 1 日
服务中心
客服
在线客服
24小时为您服务
咨询
联系我们
联系我们,为您的业务提供专属服务。
24/7 技术支持
如果您遇到寻求进一步的帮助,请过工单与我们进行联系。
24/7 即时支持
泽御云
售前客服
泽御云
泽御云
售后客服
泽御云
技术支持
评价
您对当前页面的整体感受是否满意?
😞
非常不满意
😕
不满意
😐
一般
🙂
满意
😊
非常满意