lemooljiang avatar

对Neo4j批量导入结构化数据 / ai #54

lemooljiang

Published: 20 Jun 2026 › Updated: 20 Jun 2026

对Neo4j批量导入结构化数据 / ai #54

在上一篇中我们利用大模型自身的能力来抽取文本中的关系,但是这些默认设置不是很准确。或者数据本身就存在数据库中,已经是结构化的(如 CSV、JSON),就是有逻辑和规律的数据,或者对节点和关系的产生有极其严格的业务逻辑要求,不希望依赖 LLMs 的随机性。那么,这时就可以其自身的特征来直接存入Neo4j图数据库中。

最关键的是要编写明确的 Cypher 语句(推荐用于生产环境、结构化数据)。

from langchain_neo4j import Neo4jGraph
import json

# 假设你的文本数据是一组结构化的实体关系描述
json_data = """
[
    {"source": "", "source_type": "Person", "target": "", "target_type": "Organization", "relation": "", "since": "2020"},
    {"source": "", "source_type": "Organization", "target": "", "target_type": "Location", "relation": "", "since": "1999"}
]
"""
data_list = json.loads(json_data)

graph = Neo4jGraph(url="bolt://localhost:7687", username="neo4j", password="password")

# 节点与关系的处理与写入(通过 Cypher 模版)
# 在 Neo4j 中,处理节点和关系的核心原则是 去重与合并 (MERGE)。如果使用 CREATE,每次运行都会创建重复的节点;而 MERGE 相当于 “存在则匹配,不存在则创建”。
# 我们可以利用 Neo4jGraph.query 方法,将数据作为参数传进去批量执行:
# 2.1 编写精细化的 Cypher 动态写入模板
# 注意:因为 Neo4j 标签(Label)和关系类型(Type)不能动态参数化,
# 建议在业务逻辑清晰时,针对不同的节点类型写不同的 Cypher,或者使用类似 APOC 的动态扩展。
cypher_query = """
UNWIND $data AS row
// 1. 处理源节点(去重创建)
MERGE (source:Entity {name: row.source})
ON CREATE SET source.type = row.source_type

// 2. 处理目标节点(去重创建)
MERGE (target:Entity {name: row.target})
ON CREATE SET target.type = row.target_type

// 3. 处理关系与动态属性 (这里为了兼容动态关系,使用 APOC 插件,若未装 APOC,关系名需固定)
CALL apoc.create.relationship(source, row.relation, {since: row.since}, target) YIELD rel
RETURN count(*)
"""

# 2.2 执行写入
graph.query(cypher_query, params={"data": data_list})
print("图谱数据导入成功!")


# 补充下,增加数据的cypher语句
graph.query(
"""
MERGE (m:Movie {title:'Top Gun'})
WITH m
UNWIND ['Tom Cruise', 'Val Kilmer', 'Anthony Edwards', 'Meg Ryan'] AS actor
MERGE (a:Actor {name:actor})
MERGE (a)-[:ACTED_IN]->(m)
"""
)

neo4j.jpg

到Neo4j数据库中查看相关数据

Cypher语句的核心设计解析

  • UNWIND 展开机制:
    数据中的 symptom、check 等字段是数组(如 ["紫绀", "胸痛"])。Cypher 无法直接把数组连向一个节点。我们使用 WITH row, d UNWIND row.symptom AS sym_name,将数组拍平循环,一条条地为每个症状创建节点并连线。

  • MERGE 保证幂等性:
    比如“内科”这个科室,不仅“肺泡蛋白质沉积症”有,“感冒”也有。使用 MERGE (dept:Department {name: dept_name}) 可以确保整个数据库里只有一个名叫“内科”的节点,所有相关的疾病都会连向它。

  • 关系语义化:
    通过 -[:HAS_SYMPTOM]->、-[:NEED_CHECK]-> 明确了图谱中边的含义,这对于后续构建 GraphCypherQAChain 时,大模型理解和生成正确的 Cypher 提问至关重要。

Leave 对Neo4j批量导入结构化数据 / ai #54 to:

Written by

Designer , Poet , Technology enthusiasts

Read more #cn posts


Best Posts From lemooljiang

We have not curated any of lemooljiang's posts yet. But you can encourage our curation team to review posts by visiting them regularly and by referring other readers. Because we give priority to frequently read content.

More Posts From lemooljiang