# 大模型技术之Neo4j

大语言模型(LLM)狂飙突进,但也暴露出一个软肋:幻觉和知识陈旧。为了让模型输出更可信、更实时,业界正广泛采用 检索增强生成(RAG) 技术,而 图数据库 正是 RAG 架构中承载结构化知识的绝佳载体——它将实体及其关系直接建模为节点与边,天然适合表达知识图谱。

Neo4j 是图数据库领域的“头号玩家”,它不仅查询直观、性能强劲,还与 LangChain、LlamaIndex 等主流 AI 框架深度集成。对于 AI 开发者来说,掌握 Neo4j 就等于拥有了一座可随时调用的“记忆宫殿”。这篇专栏将带你从零开始,用最短的时间打通 Neo4j 的任督二脉。

Snipaste_2026-07-02_10-22-38

# 1. 认识 Neo4j:不只是数据库

传统关系型数据库用表格和外键描述关联,一旦涉及多跳查询(比如“张艺谋合作过的演员还演过哪些电影”),SQL 就会变得异常臃肿。图数据库则直接用节点(Node)代表实体,用关系(Relationship)代表实体间的连接,数据模型和人对现实世界的认知方式高度一致。

Neo4j 由同名公司用 Java 开发,采用原生图存储与查询引擎,是目前最流行、社区最活跃的图数据库。它被广泛用在社交网络、推荐系统、知识图谱、反欺诈等场景,也是 Graph RAG 方案的首选基础设施。

适用场景速查:如果你需要处理“谁认识谁”“A通过什么路径影响B”“某节点半径三跳内所有相关对象”这类问题,Neo4j 就是比关系型数据库更合适的答案。

# 2. 环境搭建:10 分钟跑起来

Neo4j 提供了三种主要使用方式:

  • Neo4j Desktop:带图形界面的本地工具,适合学习与原型开发。
  • Neo4j Aura:官方云服务,免安装免运维。
  • OS Deployment:直接部署在服务器上,适合生产环境。

为了让你对底层有更实在的感知,我们选择在 Windows 上通过 OS Deployment 安装 Neo4j 5.26(LTS)社区版。

# 2.1 安装 JDK

Neo4j 依赖 JVM,5.26 版本要求 JDK 17 或 JDK 21。从 Oracle 官网下载对应安装包(也可从本文配套资料获取),双击安装。完成后在终端输入:

java --version
1

若能正常显示版本号,说明 JDK 就绪。

# 2.2 安装并启动 Neo4j

在 Neo4j 下载中心 (opens new window) 选择社区版压缩包,下载后解压到你喜欢的目录(比如 D:\neo4j)。

接下来配置环境变量:

  • 新建系统变量 NEO4J_HOME,值为 Neo4j 的解压路径(例如 D:\neo4j)。
  • 在 Path 变量中添加 %NEO4J_HOME%\bin。

验证配置:

neo4j --version
1

将 Neo4j 注册为系统服务并启动:

neo4j windows-service install
neo4j start
1
2

服务启动后,在浏览器中打开 http://localhost:7474。初始用户名和密码都是 neo4j,首次登录需修改密码。此时你会看到 Neo4j 自带的 Web 客户端,一切就绪。

# 3. Cypher 速成:用图表的方式思考

Cypher 是 Neo4j 的声明式查询语言,风格接近 SQL,但专为图数据设计。它的核心理念是:画出你想匹配的模式,引擎就帮你返回对应的子图。

# 3.1 图数据模型三要素

  • 节点(Node):实体。例如“王宝强”“唐探1900”。可用标签(Label)区分类型(如 :Person、:Movie),可携带若干属性(Property)。

  • 关系(Relationship):连接两个节点的有向边。必须指定一个类型(Type),也可以附加属性。

  • 路径(Path):节点与关系组成的链条,是图查询返回的核心结构。

在 Cypher 中,我们用 () 表示节点,-[]-> 表示关系,像搭积木一样把模式拼出来。

# 3.2 数据的创建与查询

创建节点

CREATE (n1:Person:Actor:Director {name: '王宝强', gender: '男'})
CREATE (n2:Movie {title: '唐探1900', released: '2025-01-29'})
1
2

查询节点

MATCH (n) RETURN n                    // 全图扫描
MATCH (n:Person) RETURN n             // 按标签筛选
MATCH (n:Person {name: '王宝强'}) RETURN n  // 按属性精确定位
1
2
3

创建关系:先定位首尾节点,再用 CREATE 画出连接。

MATCH (n1:Person {name: '王宝强'}), (n2:Movie {title: '唐探1900'})
CREATE (n1)-[:ACTED_IN {role: '阿鬼'}]->(n2)
1
2

查询关系

MATCH (n1:Person {name: '王宝强'})-[r]->(n2:Movie {title: '唐探1900'})
RETURN r
1
2

一步构建路径:在一条 CREATE 语句中同时生成节点和关系,更高效。

CREATE
  (n1:Person:Actor:Singer {name: '刘德华', gender: '男'})-
    [:ACTED_IN {roles: ['刘建明']}]->
  (n2:Movie {title: '无间道', released: '2002-12-12'})
1
2
3
4

查询路径

MATCH path = (n1:Person)-[r:ACTED_IN]->(n2:Movie)
RETURN path
1
2

# 3.3 修改与删除

使用 SET 和 REMOVE 动态调整属性或标签:

MATCH (n:Person {name: '王宝强'})
SET n.birth = '1984-05-29', n:Singer

MATCH (n:Person {name: '王宝强'})-[r:ACTED_IN]->(m:Movie {title: '唐探1900'})
REMOVE r.role
SET r.roles = ['阿鬼']
1
2
3
4
5
6

删除操作 DELETE 必须先清掉所有关联关系,否则会报错:

MATCH (n1:Person {name: '王宝强'})-[r:ACTED_IN]->(n2:Movie {title: '唐探1900'})
DELETE n1, r, n2
1
2

# 3.4 灵活的 MERGE

MERGE 是 MATCH + CREATE 的组合:存在就复用,不存在就新建。非常适合做幂等插入。

MERGE (n2:Movie {title: '唐探1900', released: '2025-01-29'})
MERGE (n1:Person:Actor:Director {name: '王宝强', gender: '男'})
  ON CREATE SET n1.create_time = datetime()
  ON MATCH SET n1.update_time = datetime()
1
2
3
4

# 4. 数据类型与常用函数

Cypher 的内置类型和函数让数据清洗与加工变得顺手。

# 4.1 数据类型速查

类型 示例 说明
String 'Neo4j', "王宝强" 单/双引号
Integer 42, 2025 整数
Float 3.14, 99.99 浮点数
Boolean true, false 布尔
List ['王宝强', '刘昊然'] 有序列表
Map {year: 2025, month:6} 键值对结构

# 4.2 函数即用

字符串处理

RETURN toUpper('neo4j')          -- 'NEO4J'
RETURN substring('neo4j', 0, 3)  -- 'neo'
RETURN replace('neo4j', 'o','O') -- 'neO4j'
RETURN trim(' hello ')           -- 'hello'
1
2
3
4

数学运算

RETURN abs(-5)      -- 5
RETURN round(3.6)   -- 4.0
RETURN floor(3.8)   -- 3.0
RETURN rand()        -- 0~1 随机数
1
2
3
4

集合操作

RETURN size(['a','b','c'])               -- 3
RETURN head(['a','b','c'])               -- 'a'
RETURN '刘昊然' IN ['王宝强','刘昊然']   -- true
1
2
3

日期时间

RETURN date()      -- 当前日期
RETURN datetime()  -- 当前日期时间
1
2

# 5. 高级查询实战

光有基础操作还不够,真实业务中需要组合出千变万化的查询。为了演示,我们先在 Neo4j 中灌入一套“人物-电影”数据,模型如下:

你可以在 Neo4j 浏览器中执行下方脚本,一键构建好示例图谱(包含 9 位演员/导演、10 部电影,以及他们之间的导演、参演、关注关系)。

// =======================
// 清空旧数据
// =======================
MATCH (n) DETACH DELETE n;

// =======================
// 创建人物节点(9人)
// =======================
CREATE
  (:Person {name:'张艺谋', birth:'1951-11-14'}),
  (:Person {name:'陈凯歌', birth:'1952-08-12'}),
  (:Person {name:'巩俐', birth:'1965-12-31'}),
  (:Person {name:'葛优', birth:'1957-04-19'}),
  (:Person {name:'章子怡', birth:'1979-02-09'}),
  (:Person {name:'刘德华', birth:'1961-09-27'}),
  (:Person {name:'吴京', birth:'1974-04-03'}),
  (:Person {name:'贾玲', birth:'1982-04-29'}),
  (:Person {name:'郭帆', birth:'1980-12-15'});

// =======================
// 创建电影节点(10部)
// =======================
CREATE
  (:Movie {title:'红高粱', year:1987, rating:8.4, genre:['文艺','历史']}),
  (:Movie {title:'活着', year:1994, rating:9.2, genre:['剧情','历史']}),
  (:Movie {title:'霸王别姬', year:1993, rating:9.6, genre:['剧情','爱情']}),
  (:Movie {title:'英雄', year:2002, rating:7.5, genre:['动作','武侠']}),
  (:Movie {title:'无间道', year:2002, rating:9.1, genre:['犯罪','悬疑']}),
  (:Movie {title:'一代宗师', year:2013, rating:8.0, genre:['动作','传记']}),
  (:Movie {title:'流浪地球', year:2019, rating:8.5, genre:['科幻','灾难']}),
  (:Movie {title:'战狼2', year:2017, rating:7.1, genre:['动作','军事']}),
  (:Movie {title:'你好,李焕英', year:2021, rating:7.7, genre:['喜剧','家庭']}),
  (:Movie {title:'满江红', year:2023, rating:7.2, genre:['悬疑','历史']});

// =======================
// 创建导演关系(9条)
// =======================
MATCH
  (zhang:Person {name:'张艺谋'}),
  (chen:Person {name:'陈凯歌'}),
  (liu:Person {name:'刘德华'}),
  (wu:Person {name:'吴京'}),
  (jia:Person {name:'贾玲'}),
  (guo:Person {name:'郭帆'}),
  (m1:Movie {title:'红高粱'}),
  (m2:Movie {title:'活着'}),
  (m3:Movie {title:'霸王别姬'}),
  (m4:Movie {title:'英雄'}),
  (m5:Movie {title:'无间道'}),
  (m6:Movie {title:'战狼2'}),
  (m7:Movie {title:'你好,李焕英'}),
  (m8:Movie {title:'流浪地球'}),
  (m9:Movie {title:'满江红'})
CREATE
  (zhang)-[:DIRECTED {award:true}]->(m1),
  (zhang)-[:DIRECTED {award:true}]->(m2),
  (zhang)-[:DIRECTED {award:false}]->(m4),
  (zhang)-[:DIRECTED {award:false}]->(m9),
  (chen)-[:DIRECTED {award:true}]->(m3),
  (liu)-[:DIRECTED {award:false}]->(m5),
  (wu)-[:DIRECTED {award:false}]->(m6),
  (jia)-[:DIRECTED {award:true}]->(m7),
  (guo)-[:DIRECTED {award:true}]->(m8);

// =======================
// 创建参演关系(11条)
// =======================
MATCH
  (gong:Person {name:'巩俐'}), (ge:Person {name:'葛优'}),
  (zhangyi:Person {name:'章子怡'}), (liu:Person {name:'刘德华'}),
  (wu:Person {name:'吴京'}), (zhang:Person {name:'张艺谋'}),
  (jia:Person {name:'贾玲'}),
  (m1:Movie {title:'红高粱'}), (m2:Movie {title:'活着'}),
  (m3:Movie {title:'霸王别姬'}), (m4:Movie {title:'英雄'}),
  (m5:Movie {title:'无间道'}), (m6:Movie {title:'流浪地球'}),
  (m7:Movie {title:'满江红'}), (m8:Movie {title:'战狼2'}),
  (m9:Movie {title:'你好,李焕英'})
CREATE
  (gong)-[:ACTED_IN {role:'九儿', award:true}]->(m1),
  (gong)-[:ACTED_IN {role:'家珍', award:false}]->(m2),
  (ge)-[:ACTED_IN {role:'福贵', award:true}]->(m2),
  (ge)-[:ACTED_IN {role:'袁四爷', award:false}]->(m3),
  (zhangyi)-[:ACTED_IN {role:'如月', award:false}]->(m4),
  (zhangyi)-[:ACTED_IN {role:'宫二', award:true}]->(m7),
  (liu)-[:ACTED_IN {role:'刘建明', award:false}]->(m5),
  (wu)-[:ACTED_IN {role:'刘培强', award:true}]->(m6),
  (zhang)-[:ACTED_IN {role:'秦桧', award:false}]->(m7),
  (wu)-[:ACTED_IN {role:'冷锋', award:true}]->(m8),
  (jia)-[:ACTED_IN {role:'贾晓玲', award:true}]->(m9);

// =======================
// 创建关注关系(11条)
// =======================
MATCH
  (gong:Person {name:'巩俐'}), (zhang:Person {name:'张艺谋'}),
  (zhangyi:Person {name:'章子怡'}), (chen:Person {name:'陈凯歌'}),
  (ge:Person {name:'葛优'}), (liu:Person {name:'刘德华'}),
  (wu:Person {name:'吴京'}), (jia:Person {name:'贾玲'}),
  (guo:Person {name:'郭帆'})
CREATE
  (gong)-[:FOLLOWS]->(zhang),
  (zhangyi)-[:FOLLOWS]->(zhang),
  (zhang)-[:FOLLOWS]->(chen),
  (ge)-[:FOLLOWS]->(chen),
  (liu)-[:FOLLOWS]->(zhang),
  (gong)-[:FOLLOWS]->(zhangyi),
  (wu)-[:FOLLOWS]->(zhang),
  (jia)-[:FOLLOWS]->(zhang),
  (guo)-[:FOLLOWS]->(zhang),
  (liu)-[:FOLLOWS]->(wu),
  (zhang)-[:FOLLOWS]->(guo);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111

# 5.1 过滤:不只是 WHERE

WHERE 子句是筛选数据的看门人,支持比较、逻辑、集合、字符串匹配和空值判断。

-- 1970年后出生的演员
MATCH (p:Person)
WHERE p.birth > '1970-01-01'
RETURN p.name, p.birth
1
2
3
4
-- 高分且老电影
MATCH (m:Movie)
WHERE m.rating > 8.0 AND m.year < 2000
RETURN m.title, m.year, m.rating
1
2
3
4
-- 历史类影片
MATCH (m:Movie)
WHERE '历史' IN m.genre
RETURN m.title, m.genre
1
2
3
4
-- 姓张的人
MATCH (p:Person)
WHERE p.name CONTAINS '张'
RETURN p.name
1
2
3
4

# 5.2 排序与分页

ORDER BY 控制升降序,SKIP 和 LIMIT 实现分页,和 SQL 几乎一个思路。

MATCH (m:Movie)
RETURN m.title, m.rating
ORDER BY m.rating DESC
LIMIT 3
1
2
3
4
MATCH (m:Movie)
RETURN m.title, m.year
ORDER BY m.year DESC
SKIP 5
LIMIT 5
1
2
3
4
5

# 5.3 聚合统计

Cypher 的聚合函数(count、avg、sum、max、min、collect 等)会自动按非聚合字段分组,无需显式 GROUP BY。

-- 演员人数(去重)
MATCH (p:Person)-[:ACTED_IN]->()
RETURN count(DISTINCT p) AS 演员人数
1
2
3
-- 每人参演电影数
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
RETURN p.name, count(m) AS 参演电影数
1
2
3
-- 导演作品列表
MATCH (p:Person)-[:DIRECTED]->(m:Movie)
RETURN p.name, collect(m.title) AS 导演作品
1
2
3

# 5.4 联合与子查询

UNION 和 UNION ALL 用于拼接多个结果集,注意列数和类型必须一致。

MATCH (p:Person {name:'张艺谋'})-[:DIRECTED]->(m:Movie)
RETURN m.title AS title, '导演' AS role
UNION
MATCH (p:Person {name:'张艺谋'})-[:ACTED_IN]->(m:Movie)
RETURN m.title AS title, '演员' AS role
1
2
3
4
5

子查询用 CALL (变量) { ... } 包裹,可对每行输入执行独立匹配:

MATCH (p:Person)-[:DIRECTED]->()
WITH DISTINCT p
CALL (p) {
  MATCH (p)-[:DIRECTED]->(m:Movie)
  RETURN m.title AS title, m.rating AS rating
  ORDER BY rating DESC
  LIMIT 1
}
RETURN p.name AS 导演, title AS 最高评分作品, rating AS 评分
1
2
3
4
5
6
7
8
9

这里的 WITH DISTINCT p 负责将中间结果去重后传递到子查询,CALL (p) 则让每一行数据都执行一次内部匹配。

# 5.5 灵活的模式匹配

标签表达式:&(与)、|(或)、!(非)组合节点标签。

MATCH (n:(Person|Movie)) RETURN n            -- Person 或 Movie
MATCH (n:(!Person)) RETURN n                 -- 不是 Person
1
2

关系也可以使用类型表达式:

MATCH (:Person {name: '张艺谋'})-[:ACTED_IN|DIRECTED]->(m:Movie)
RETURN DISTINCT m.title
1
2

无方向查询:去掉关系箭头,匹配任意方向。

MATCH (p1:Person {name: '巩俐'})-[:ACTED_IN]-(m:Movie)-[:ACTED_IN]-(p2:Person)
RETURN path
1
2

变长路径:用 {m,n} 指定跳数范围,非常适合做社交网络扩散分析。

-- 张艺谋粉丝的粉丝(2跳)
MATCH path= (a:Person)-[:FOLLOWS]->{2}(b:Person{name:'张艺谋'})
RETURN path
1
2
3

# 6. 约束:让数据干净起来

Neo4j 支持多种约束来维护数据完整性。在社区版中我们最常用的是属性唯一性约束,它可以确保某个属性在指定标签的所有节点(或指定类型的关系)中不重复。

创建唯一约束

CREATE CONSTRAINT unique_user_id
FOR (u:User)
REQUIRE u.userId IS UNIQUE;
1
2
3

此后,如果尝试插入相同 userId 的节点:

CREATE (u:User {userId: 'u001', name: 'Alice'});
CREATE (u:User {userId: 'u001', name: 'Charlie'});   // 报错!
1
2

Neo4j 会抛出 ConstraintValidationFailed,杜绝脏数据进入图谱。

查看已有约束:

SHOW CONSTRAINTS;
1

删除约束(例如重构数据模型时):

DROP CONSTRAINT unique_user_id;
1

小贴士:企业版还支持属性存在约束、属性类型约束和复合键约束,但社区版足以覆盖大多数入门和学习场景。

# 7. 用 Python 撬动 Neo4j

生产环境中,我们往往通过代码与图数据库交互。Neo4j 官方 Python 驱动简洁高效,安装只需一行:

pip install neo4j
1

# 7.1 建立连接

Driver 对象是连接池的入口,线程安全但创建成本高,应用中应该全局复用。推荐使用 with 语句自动管理资源。

from neo4j import GraphDatabase

URI = "neo4j://localhost"
AUTH = ("neo4j", "password")

with GraphDatabase.driver(URI, auth=AUTH) as driver:
    driver.verify_connectivity()
    print("Connection established.")
1
2
3
4
5
6
7
8

# 7.2 执行查询

execute_query() 是执行 Cypher 最便捷的方式,它返回一个命名元组,包含记录列表、执行摘要和字段名。

records, summary, keys = driver.execute_query(
    """
    MATCH (p:Person{name:$name})-[r:DIRECTED]->(m:Movie)
    WHERE m.year > $year
    RETURN p.name AS director, m.year AS year, m.title AS movie
    """,
    parameters_={"name": "张艺谋", "year": 1990},
    database_="neo4j"
)

print(f"查询返回了 {len(records)} 条记录")
for record in records:
    print(f"{record['director']}在{record['year']}年拍摄了《{record['movie']}》")
1
2
3
4
5
6
7
8
9
10
11
12
13

通过参数化查询($name、$year),你既提升了性能,也规避了 Cypher 注入风险。execute_query 足以满足大多数事务性操作;如需更精细的事务控制,驱动也提供了 session 级别的 API,留给读者延伸探索。

# 写在最后

从单机安装到 Python 集成,你已经走完了 Neo4j 入门全流程。回顾一下关键收获:

  • 图数据库用节点+关系直击问题本质。
  • Cypher 让你像画图一样查询数据,学习曲线平滑。
  • 高级模式匹配、聚合、分页、约束等功能足以应对复杂业务。
  • Python 驱动让 Neo4j 无缝融入现代 AI 技术栈。

在大模型时代,图谱不仅是知识的容器,更是将符号逻辑与深度学习结合的关键桥梁。无论你是在构建 Graph RAG,还是做用户画像、风控分析,Neo4j 都能成为你的得力助手。动手把今天的内容跑一遍,你会发现,图的世界比想象中更精彩。

最近更新: 2026/9/7
 |  Copyright © -Present Kelsen All Rights Reserved. | Author KelsenJing