第一章:Neo4j 基础概念
1.1 图数据库基本原理
| 概念名称 | 说明 | 注意事项 |
|---|
| 图数据库 | 一种以图结构(节点与边)存储和查询数据的 NoSQL 数据库,强调实体间关系 | 不适合高频率事务性写入场景;更适合关联密集型查询 |
| 属性图模型 | Neo4j 使用的图模型,节点和关系均可携带键值对形式的属性 | 关系必须有方向和类型,不可孤立存在 |
| 白板友好性 | 图模型可直接映射现实世界的实体与关系,建模直观 | 避免过度抽象,应贴近业务语义 |
| 遍历效率 | 通过指针直接跳转到相邻节点,避免传统 JOIN 操作 | 性能优势在深度关联查询(如”朋友的朋友”)中尤为明显 |
1.2 Neo4j 核心组件与架构
| 组件名称 | 说明 | 注意事项 |
|---|
| Kernel | Neo4j 的核心引擎,负责存储、事务、索引和查询执行 | 所有上层功能(如 Cypher、驱动)均构建于 Kernel 之上 |
| Storage Engine | 基于本地文件系统的原生存储引擎,支持 ACID 事务 | 默认使用嵌入式存储,不依赖外部数据库 |
| Cypher Runtime | Cypher 查询的执行引擎,包含解释器与编译器模式 | 企业版支持更高效的编译模式 |
| Bolt 协议 | Neo4j 官方二进制通信协议,用于驱动与数据库之间的高效连接 | 推荐使用 Bolt 而非 HTTP REST API 以获得更好性能 |
| Web 管理界面 | 内置的浏览器 UI(通常访问 http://localhost:7474) | 仅用于开发调试,生产环境建议关闭或限制访问 |
| Plugin 扩展机制 | 支持通过 APOC、GDS 等插件扩展功能 | 插件需与 Neo4j 版本兼容,安装后需重启服务 |
1.3 节点、关系、属性与标签
| 概念名称 | 说明 | 注意事项 |
|---|
| 节点(Node) | 表示实体(如”人""商品”),是图的基本单元 | 节点可拥有零个或多个标签,用于分类 |
| 关系(Relationship) | 连接两个节点的有向边,具有类型(如”FRIEND_OF”) | 关系必须有起点和终点,不可悬空;关系本身也可带属性 |
| 属性(Property) | 键值对(key-value),可附加在节点或关系上 | 键为字符串,值支持字符串、数字、布尔、列表等(不支持嵌套对象) |
| 标签(Label) | 用于对节点进行分组(如”User""Product”) | 一个节点可有多个标签;标签用于索引和查询优化 |
| 关系类型(Relationship Type) | 定义关系的语义类别(如”WORKS_AT”) | 类型名区分大小写,通常用大写;不可动态修改已有关系的类型 |
1.4 Cypher 查询语言简介
| 方法/子句名称 | 语法示例 | 用途 | 代码示例 | 注意事项 |
|---|
| MATCH | MATCH (n:Label) | 匹配图中的节点或关系 | MATCH (p:Person {name: 'Alice'}) RETURN p | 必须配合 RETURN 或其他子句使用;不加条件会全图扫描 |
| CREATE | CREATE (n:Label {prop: value}) | 创建新节点或关系 | CREATE (:Person {name: 'Bob', age: 30}) | 每次执行都会创建新实体,可能产生重复 |
| MERGE | MERGE (n:Label {prop: value}) | 匹配存在则返回,不存在则创建 | MERGE (p:Person {name: 'Charlie'}) ON CREATE SET p.created = timestamp() | 建议在 MERGE 条件字段上建立索引以提升性能 |
| RETURN | RETURN n, n.name | 返回查询结果 | MATCH (n) RETURN count(n) AS total | 可使用别名、表达式、函数 |
| WHERE | WHERE n.age > 25 | 添加过滤条件 | MATCH (n:Person) WHERE n.age >= 18 RETURN n.name | 支持 AND/OR/NOT、正则、IN、EXISTS 等 |
| SET | SET n.status = 'active' | 为节点或关系添加或更新属性 | MATCH (n {name: 'Alice'}) SET n.lastLogin = date() | 可同时设置多个属性:SET n.prop1 = v1, n.prop2 = v2 |
| DELETE | DELETE r | 删除关系 | MATCH ()-[r:FRIEND]->() DELETE r | 不能删除仍有关联关系的节点 |
| DETACH DELETE | DETACH DELETE n | 删除节点及其所有关系 | MATCH (n:TempUser) DETACH DELETE n | 谨慎使用,可能引发级联删除 |
第二章:Neo4j 安装与配置
2.1 安装 Neo4j(社区版/企业版)
| 步骤名称 | 操作细节 | 注意事项 |
|---|
| 选择版本 | 访问 https://neo4j.com/download/,下载社区版(免费)或企业版(需许可) | 社区版不支持集群、高级监控和热备份;开发测试推荐社区版 |
| 安装方式(Linux/macOS) | 解压 tar.gz 包:tar -xzf neo4j-community-5.x.x-unix.tar.gz | 需预装 Java 17(Neo4j 5.x 起要求 JDK 17+) |
| 安装方式(Windows) | 运行 .exe 安装程序或解压 zip 包 | 建议安装路径不含空格或中文 |
| 验证安装 | 进入 bin 目录,执行 ./neo4j version(Linux/macOS)或 neo4j.bat version(Windows) | 应输出版本号如 “5.18.0” |
| 设置环境变量(可选) | 将 neo4j/bin 加入 PATH,便于全局调用命令 | 修改 ~/.bashrc 或 ~/.zshrc(macOS/Linux) |
2.2 启动与停止服务(命令行方式)
| 命令名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 启动服务(前台) | ./neo4j console | 以控制台模式启动,日志直接输出 | cd neo4j/bin && ./neo4j console | 适用于调试;关闭终端即停止服务 |
| 启动服务(后台) | ./neo4j start | 以后台守护进程方式启动 | ./neo4j start | 首次启动会初始化数据目录 |
| 停止服务 | ./neo4j stop | 停止 Neo4j 服务 | ./neo4j stop | 确保无活跃事务再停止 |
| 重启服务 | ./neo4j restart | 重启服务 | ./neo4j restart | 等效于 stop + start |
| 查看服务状态 | ./neo4j status | 检查服务是否运行 | ./neo4j status | 返回 “Neo4j is running” 或 “Neo4j is not running” |
| 强制终止(紧急情况) | kill -9 $(cat data/neo4j.pid) | 强制杀死进程 | kill -9 $(cat data/neo4j.pid) | 仅在服务无响应时使用,可能导致数据损坏 |
2.3 配置文件详解(neo4j.conf)
| 配置项名称 | 默认值 / 示例值 | 说明 | 注意事项 |
|---|
dbms.default_database | neo4j | 默认数据库名称 | Neo4j 4.0+ 支持多数据库,此为启动后自动连接的库 |
server.http.listen_address | localhost:7474 | HTTP 服务监听地址 | 生产环境若需远程访问,改为 0.0.0.0:7474,但需配合防火墙 |
server.bolt.listen_address | localhost:7687 | Bolt 协议监听地址 | 驱动连接使用此端口 |
dbms.security.auth_enabled | true | 是否启用身份认证 | 开发环境可设为 false,生产环境必须为 true |
dbms.directories.data | data | 数据存储目录 | 可修改为绝对路径以分离数据盘 |
dbms.memory.heap.initial_size | 512m | JVM 初始堆内存 | 根据机器内存调整,建议不超过物理内存的 50% |
dbms.memory.heap.max_size | 512m | JVM 最大堆内存 | 同上 |
dbms.logs.http.enabled | true | 是否记录 HTTP 请求日志 | 调试 API 调用时有用 |
cypher.default_language_version | 5.0 | 默认 Cypher 语言版本 | 影响语法兼容性 |
注:修改 neo4j.conf 后需重启服务生效。
2.4 初始安全设置与用户管理
| 操作名称 | 命令语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 首次登录 Web 控制台 | 浏览器访问 http://localhost:7474 | 使用默认凭据登录 | 用户名:neo4j,密码:首次登录强制修改 | 初始密码必须修改,否则无法执行写操作 |
| 修改当前用户密码 | :password | 在 Web 控制台中交互式修改 | 输入旧密码 → 输入新密码 → 确认 | 仅限已认证用户 |
| 创建新用户(cypher-shell) | CREATE USER username SET PASSWORD 'pass' CHANGE NOT REQUIRED | 创建用户并设密码 | CREATE USER alice SET PASSWORD 'secret123' CHANGE NOT REQUIRED | 需具备 admin 权限;CHANGE NOT REQUIRED 表示不要求首次登录改密 |
| 授予角色 | GRANT ROLE role_name TO username | 分配内置角色(如 reader, writer) | GRANT ROLE writer TO alice | 内置角色:admin, architect, publisher, reader, writer |
| 查看用户列表 | SHOW USERS | 列出所有用户及其状态 | SHOW USERS | 返回用户名、是否活跃、角色列表 |
| 删除用户 | DROP USER username | 删除指定用户 | DROP USER bob | 无法删除当前会话用户 |
| 重置 admin 密码(离线) | ./neo4j-admin dbms set-initial-password newpass | 重置初始密码(服务未运行时) | ./neo4j-admin dbms set-initial-password myNewPass | 仅在忘记密码且无其他 admin 用户时使用;服务必须停止 |
第三章:命令行工具使用
3.1 neo4j-admin 工具常用命令
| 命令名称 | 语法示例 | 用途 | 代码示例 | 注意事项 |
|---|
set-initial-password | neo4j-admin dbms set-initial-password | 设置初始 admin 密码 | ./bin/neo4j-admin dbms set-initial-password MyPass123 | 仅在首次启动前或重置密码时使用;服务必须停止 |
dump | neo4j-admin database dump --to= | 备份数据库为 dump 文件 | ./bin/neo4j-admin database dump neo4j --to=/backups/neo4j-2026.dump | 需指定数据库名(默认 neo4j);服务必须停止 |
load | neo4j-admin database load --database= --force | 从 dump 文件恢复数据库 | ./bin/neo4j-admin database load /backups/neo4j-2026.dump --database=neo4j --force | 会覆盖目标数据库;服务必须停止 |
memrec | neo4j-admin memrec | 推荐 JVM 内存配置 | ./bin/neo4j-admin memrec | 根据当前机器内存输出建议的 heap 和 pagecache 值 |
server report | neo4j-admin server report | 生成诊断报告(含日志、配置等) | ./bin/neo4j-admin server report | 用于向 Neo4j 支持团队提交问题 |
help | neo4j-admin help | 查看所有子命令 | ./bin/neo4j-admin help | 可接具体子命令查看用法,如 neo4j-admin help dump |
3.2 cypher-shell 命令行客户端
| 命令/用法名称 | 语法示例 | 用途 | 代码示例 | 注意事项 |
|---|
| 连接本地数据库 | cypher-shell | 使用默认地址连接 | ./bin/cypher-shell | 默认连接 bolt://localhost:7687,使用 neo4j/neo4j 凭据 |
| 指定连接参数 | cypher-shell -a bolt://host:port -u user -p password | 自定义连接 | ./bin/cypher-shell -a bolt://192.168.1.10:7687 -u admin -p secret | 支持 --encryption=false(非 TLS 环境) |
| 执行单条 Cypher 语句 | echo "MATCH (n) RETURN count(n)" | cypher-shell | 非交互式执行 | echo "CREATE (:Test {id: 1})" | ./bin/cypher-shell | 适用于脚本自动化 |
| 启用多行模式 | :set multiLine true | 允许输入跨多行的查询 | 在 cypher-shell 中输入 :set multiLine true | 输入 ; 结束多行语句 |
| 显示执行计划 | EXPLAIN MATCH (n) RETURN n | 查看逻辑计划 | EXPLAIN MATCH (p:Person) RETURN p.name | 不实际执行查询 |
| 查看元命令 | :help | 列出所有元命令 | 在交互模式中输入 :help | 其他元命令包括 :exit, :history, :server |
| 退出客户端 | :exit 或 Ctrl+D | 退出交互会话 | :exit | - |
3.3 数据导入与导出(CSV、dump)
| 操作名称 | 命令/方法 | 用途 | 代码示例 | 注意事项 |
|---|
| 使用 LOAD CSV 导入 | Cypher 语句:LOAD CSV FROM 'file:///data.csv' AS row | 从 CSV 文件导入数据 | LOAD CSV WITH HEADERS FROM 'file:///users.csv' AS r CREATE (:User {name: r.name, age: toInteger(r.age)}) | CSV 文件需放在 Neo4j 的 import 目录下(由 dbms.directories.import 控制) |
| 导出为 CSV(cypher-shell) | echo "MATCH (n) RETURN n.name, n.age" | cypher-shell -u neo4j -p pass > out.csv | 将查询结果导出为 CSV | echo "MATCH (u:User) RETURN u.name, u.email" | ./bin/cypher-shell -a bolt://localhost:7687 -u neo4j -p mypass > users.csv | 需处理表头和分隔符;适合小规模数据 |
| dump 全库备份 | neo4j-admin database dump neo4j --to=/backup/neo4j.dump | 二进制全量备份 | ./bin/neo4j-admin database dump neo4j --to=/mnt/backup/neo4j.dump | 服务必须停止;备份不可读,仅用于恢复 |
| load 全库恢复 | neo4j-admin database load /backup/neo4j.dump --database=neo4j --force | 从 dump 恢复 | ./bin/neo4j-admin database load /mnt/backup/neo4j.dump --database=neo4j --force | 会清空目标数据库;服务必须停止 |
| 使用 APOC 导出子图 | CALL apoc.export.cypher.all("graph.cypher", {}) | 导出为可重放的 Cypher 脚本 | CALL apoc.export.cypher.query("MATCH (n)-[r]->(m) RETURN n,r,m", "subgraph.cypher", {}) | 需先安装 APOC 插件 |
3.4 日志查看与故障排查
| 日志/操作名称 | 文件路径或命令 | 用途 | 操作细节 | 注意事项 |
|---|
| 查询日志 | logs/query.log | 记录所有 Cypher 查询 | tail -f logs/query.log | 需在 neo4j.conf 中启用 dbms.logs.query.enabled=true |
| HTTP 访问日志 | logs/http.log | 记录 Web 控制台和 REST API 请求 | grep "POST /db" logs/http.log | 启用需设置 dbms.logs.http.enabled=true |
| 错误日志 | logs/neo4j.log | 主日志,含启动、错误、警告信息 | grep "ERROR" logs/neo4j.log | 服务启动失败时首要查看此文件 |
| GC 日志 | logs/gc.log | JVM 垃圾回收日志 | cat logs/gc.log | 需在 neo4j.conf 中配置 JVM 参数开启 |
| 检查端口占用 | lsof -i :7474 或 netstat -tulnp | grep 7474 | 确认 Neo4j 端口是否监听 | lsof -i :7687 | 若端口被占,需 kill 进程或修改配置 |
| 验证数据目录权限 | ls -ld data/ | 检查 Neo4j 是否有读写权限 | chmod -R 755 data/(若权限不足) | 启动失败常见原因为 data 目录无写权限 |
| 清理临时文件 | rm -rf data/databases/*/transaction data/databases/*/index/tmp | 手动清理事务或索引临时文件 | 仅在服务停止且确认无数据损坏风险时操作 | 操作前务必备份;错误清理可能导致数据丢失 |
第四章:Cypher 查询语言详解
4.1 CREATE / MERGE 创建数据
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| CREATE | CREATE (variable:Label {key: value}) | 创建新节点或关系 | CREATE (:Person {name: 'Alice', age: 30}) | 每次执行都会创建新实体,可能产生重复;不检查是否存在 |
| CREATE(关系) | CREATE (a)-[:REL_TYPE {prop: val}]->(b) | 创建带属性的关系 | MATCH (a:Person {name:'Alice'}), (b:Person {name:'Bob'}) CREATE (a)-[:FRIEND {since: 2020}]->(b) | 起点和终点必须已存在或在同一语句中创建 |
| MERGE | MERGE (variable:Label {key: value}) | 匹配存在则返回,不存在则创建 | MERGE (p:Person {name: 'Charlie'}) ON CREATE SET p.created = timestamp() | 建议在 MERGE 条件字段上建立索引,否则性能极差 |
| MERGE(关系) | MERGE (a)-[:REL_TYPE]->(b) | 确保关系唯一性 | MATCH (a:Person {name:'Alice'}), (b:Person {name:'Bob'}) MERGE (a)-[:KNOWS]->(b) | 若关系已存在,不会重复创建;但若节点对不同,仍会新建 |
| ON CREATE / ON MATCH | MERGE ... ON CREATE SET ... ON MATCH SET ... | 分支设置属性 | MERGE (u:User {email: 'x@y.com'}) ON CREATE SET u.status = 'new' ON MATCH SET u.lastSeen = timestamp() | ON CREATE 仅在新建时触发,ON MATCH 仅在匹配时触发 |
4.2 MATCH 查询图数据
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| MATCH(节点) | MATCH (n:Label) | 匹配指定标签的节点 | MATCH (p:Person) RETURN p.name | 不加 WHERE 会全图扫描,大数据量下性能差 |
| MATCH(关系) | MATCH (a)-[r:TYPE]->(b) | 匹配特定类型的关系 | MATCH (a:Person)-[r:FRIEND]->(b:Person) RETURN a.name, b.name | 关系变量 r 可用于返回或过滤 |
| MATCH(无向关系) | MATCH (a)-[r]-(b) | 匹配任意方向的关系 | MATCH (a)-[:WORKS_AT]-(c:Company) RETURN a.name, c.name | 实际存储仍为有向,查询时忽略方向 |
| MATCH(可变长度路径) | MATCH (a)-[*1..3]->(b) | 匹配 1 到 3 跳的关系 | MATCH (p1:Person)-[:FRIEND*2]->(p2:Person) RETURN p1.name, p2.name | 长度范围越大,结果爆炸风险越高;建议限制上限(如 *1..5) |
| OPTIONAL MATCH | OPTIONAL MATCH (a)-[r]->(b) | 类似 LEFT JOIN | MATCH (p:Person) OPTIONAL MATCH (p)-[r:OWNS]->(c:Car) RETURN p.name, c.model | 若无匹配,c 为 null,不会丢弃 p 行 |
4.3 WHERE / RETURN / ORDER BY / LIMIT 过滤与投影
| 子句名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| WHERE | WHERE condition | 过滤匹配结果 | MATCH (p:Person) WHERE p.age > 25 RETURN p.name | 支持 AND/OR/NOT、IN、STARTS WITH、CONTAINS、正则 =~ |
| RETURN | RETURN expression [AS alias] | 指定返回内容 | MATCH (p:Person) RETURN p.name AS name, p.age | 可返回节点、关系、属性、表达式、函数结果 |
| RETURN DISTINCT | RETURN DISTINCT value | 去重返回 | MATCH (p:Person)-[:LIVES_IN]->(c:City) RETURN DISTINCT c.name | 自动去重,适用于聚合前筛选 |
| ORDER BY | ORDER BY expression [ASC/DESC] | 排序结果 | MATCH (p:Person) RETURN p.name ORDER BY p.age DESC | 多字段排序:ORDER BY p.age, p.name |
| LIMIT | LIMIT n | 限制返回行数 | MATCH (p:Person) RETURN p.name LIMIT 10 | 常用于分页;需配合 ORDER BY 保证结果稳定 |
| SKIP / LIMIT | SKIP m LIMIT n | 分页查询 | MATCH (p:Person) RETURN p.name ORDER BY p.id SKIP 20 LIMIT 10 | 第一页 SKIP 0;注意深度分页性能问题 |
4.4 SET / REMOVE 修改与删除属性
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| SET(更新属性) | SET variable.property = value | 设置或更新属性 | MATCH (p:Person {name: 'Alice'}) SET p.age = 31 | 若属性不存在则新增 |
| SET(多个属性) | SET variable += {k1: v1, k2: v2} | 批量更新(不覆盖其他属性) | MATCH (p:Person {name: 'Bob'}) SET p += {city: 'NYC', status: 'active'} | 使用 += 可保留原有属性 |
| SET(添加标签) | SET variable:Label1:Label2 | 为节点添加标签 | MATCH (p:Person {name: 'Eve'}) SET p:Admin:VIP | 标签不可用于关系 |
| REMOVE(删除属性) | REMOVE variable.property | 删除属性 | MATCH (p:Person) REMOVE p.tempFlag | 属性不存在时不报错 |
| REMOVE(移除标签) | REMOVE variable:Label | 移除节点标签 | MATCH (p:TempUser) REMOVE p:TempUser | 不能移除最后一个标签(节点至少有一个标签) |
4.5 DELETE / DETACH DELETE 删除节点与关系
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| DELETE(关系) | DELETE relationship_variable | 删除关系 | MATCH ()-[r:TEMP]->() DELETE r | 只能删除关系,不能删除带关系的节点 |
| DELETE(孤立节点) | DELETE node_variable | 删除无任何关系的节点 | MATCH (n:Temp) WHERE NOT (n)--() DELETE n | 若节点有关联关系,DELETE 会失败并报错 |
| DETACH DELETE | DETACH DELETE node_variable | 删除节点及其所有关系 | MATCH (n:DeprecatedUser) DETACH DELETE n | 谨慎使用!会级联删除所有连接关系 |
| 批量删除 | MATCH (n:Log) WHERE n.ts < 1700000000 DETACH DELETE n | 删除大量数据 | MATCH (n:Session) WHERE n.expired = true DETACH DELETE n | 建议分批操作(如 LIMIT 1000),避免事务过大 |
4.6 WITH / UNWIND 流程控制
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| WITH | WITH expression AS alias | 将前步结果传递给后续查询 | MATCH (p:Person) WITH p WHERE p.age > 30 RETURN p.name | 可用于中间过滤、聚合、重命名 |
| WITH + collect | MATCH (p:Person)-[:FRIEND]->(f) WITH p, collect(f.name) AS friends RETURN p.name, friends | 分组收集关联数据 | 同上 | collect() 会将多行合并为列表 |
| UNWIND | UNWIND list_expression AS item | 将列表展开为多行 | UNWIND ['A', 'B', 'C'] AS letter CREATE (:Tag {name: letter}) | 常用于从应用传入列表批量创建 |
| UNWIND + range | UNWIND range(1, 5) AS i CREATE (:Counter {id: i}) | 生成序列 | UNWIND range(0, 9) AS n RETURN n * n | range(start, end) 生成整数列表 |
| WITH + LIMIT 分页中间处理 | MATCH (e:Event) WITH e ORDER BY e.time DESC LIMIT 100 MATCH (e)<-[:PARTICIPATED]-(u) RETURN u.name | 先筛选再关联 | 避免先关联再 LIMIT 导致结果不准 | 顺序影响语义和性能 |
4.7 函数与聚合(count, collect, exists 等)
| 函数名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
count(*) | count(*) | 统计行数 | MATCH (p:Person) RETURN count(*) AS total | 包含 null 行 |
count(expr) | count(n) | 统计非 null 值数量 | MATCH (a)-[r]->(b) RETURN count(r) | 忽略 null |
collect() | collect(property) | 收集值为列表 | MATCH (p:Person) RETURN collect(p.name) | 保留重复值 |
exists() | exists(variable.property) | 判断属性是否存在 | MATCH (p:Person) WHERE exists(p.email) RETURN p.name | 也可用于关系:exists((p)-[:FRIEND]->()) |
toInteger(), toString() | toInteger('123') | 类型转换 | MATCH (n) WHERE toInteger(n.age) > 18 RETURN n | 转换失败返回 null |
size() | size(list) 或 size(pattern) | 获取列表长度或路径跳数 | MATCH p = (a)-[:FRIEND*1..3]->(b) RETURN size(p) | size((a)-->(b)) 返回关系数 |
coalesce() | coalesce(a, b, ...) | 返回第一个非 null 值 | MATCH (p:Person) RETURN coalesce(p.nick, p.name) | 类似 SQL 的 COALESCE |
min(), max(), avg(), sum() | avg(n.age) | 数值聚合 | MATCH (p:Person) RETURN avg(p.age), max(p.age) | 仅作用于数值类型 |
4.8 索引与约束(CREATE INDEX / CONSTRAINT)
| DDL 名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 创建 B-tree 索引 | CREATE INDEX [index_name] FOR (n:Label) ON (n.property) | 加速等值/范围查询 | CREATE INDEX person_name_idx FOR (p:Person) ON (p.name) | Neo4j 5.x 默认使用 B-tree;旧版用 CREATE INDEX ON :Label(prop) |
| 创建全文索引 | CREATE FULLTEXT INDEX [name] FOR (n:Label) ON EACH [prop_list] | 支持文本模糊搜索 | CREATE FULLTEXT INDEX book_title_ft FOR (b:Book) ON EACH [b.title, b.desc] | 查询需用 db.index.fulltext.queryNodes('name', 'keyword') |
| 创建唯一约束 | CREATE CONSTRAINT [name] FOR (n:Label) REQUIRE n.property IS UNIQUE | 确保属性唯一 | CREATE CONSTRAINT user_email_unique FOR (u:User) REQUIRE u.email IS UNIQUE | 自动创建索引;插入重复值会失败 |
| 创建存在性约束(企业版) | CREATE CONSTRAINT [name] FOR (n:Label) REQUIRE n.property IS NOT NULL | 禁止属性为 null | CREATE CONSTRAINT product_sku_notnull FOR (p:Product) REQUIRE p.sku IS NOT NULL | 社区版不支持 |
| 查看索引/约束 | SHOW INDEXES / SHOW CONSTRAINTS | 列出所有索引或约束 | SHOW INDEXES YIELD name, type, entityType, labelsOrTypes, properties | 可配合 WHERE 过滤 |
| 删除索引 | DROP INDEX index_name | 删除指定索引 | DROP INDEX person_name_idx | 删除后查询性能可能下降 |
| 删除约束 | DROP CONSTRAINT constraint_name | 删除约束 | DROP CONSTRAINT user_email_unique | 删除唯一约束后,原索引也会被移除 |
第五章:高级功能与优化
5.1 全文索引与文本搜索
| 方法/操作名称 | 语法/操作细节 | 用途 | 代码示例 | 注意事项 |
|---|
| 创建全文索引 | CREATE FULLTEXT INDEX index_name FOR (n:Label) ON EACH [prop1, prop2] | 为指定标签和属性创建全文索引 | CREATE FULLTEXT INDEX article_fulltext FOR (a:Article) ON EACH [a.title, a.content] | 支持多属性;仅支持字符串类型;Neo4j 4.3+ 语法 |
| 查询全文索引 | CALL db.index.fulltext.queryNodes('index_name', 'search_query') YIELD node, score | 执行全文搜索并返回匹配节点 | CALL db.index.fulltext.queryNodes('article_fulltext', 'database~') YIELD node, score RETURN node.title, score | 使用 Lucene 语法(如 fuzzy ~、wildcard *、phrase "...") |
| 删除全文索引 | DROP INDEX index_name | 删除全文索引 | DROP INDEX article_fulltext | 删除后无法再使用该索引查询 |
| 列出全文索引 | SHOW FULLTEXT INDEXES | 查看所有全文索引 | SHOW FULLTEXT INDEXES | 返回索引名、实体类型、属性列表等 |
| 更新延迟(索引异步更新) | 全文索引非实时生效 | 新增数据可能延迟数秒才可搜到 | CREATE (:Article {title: 'New'}); CALL db.index.fulltext.queryNodes('article_fulltext', 'New') YIELD node RETURN node | 可通过 db.awaitIndexes() 等待 |
| 自定义分析器(企业版) | 在 neo4j.conf 中配置 | 控制分词行为 | dbms.fulltext.analyzer.default=english | 社区版仅支持默认分析器 |
5.2 APOC 插件安装与使用
| 操作/方法名称 | 语法/操作细节 | 用途 | 代码示例 | 注意事项 |
|---|
| 安装 APOC(社区版) | 将 apoc-*.jar 放入 plugins 目录,并在 neo4j.conf 启用 | 扩展 Cypher 功能 | 1. 下载对应版本 APOC jar;2. 放入 $NEO4J_HOME/plugins/;3. 添加配置:dbms.security.procedures.unrestricted=apoc.*、dbms.security.procedures.allowlist=apoc.* | 必须与 Neo4j 版本严格匹配(如 5.18 配 apoc-5.18.x) |
| 验证安装 | CALL apoc.help('apoc') | 检查 APOC 是否可用 | CALL apoc.version() | 返回 APOC 版本号 |
| 导出子图为 Cypher | CALL apoc.export.cypher.query(query, file, config) | 生成可重放的 Cypher 脚本 | CALL apoc.export.cypher.query("MATCH (p:Person)-[r]->(c:Company) RETURN p,r,c", "export.cypher", {format: 'plain'}) | 需启用 apoc.export.file.enabled=true(默认 false) |
| 条件创建(upsert) | CALL apoc.do.when(condition, ifQuery, elseQuery, params) | 条件分支执行 | CALL apoc.do.when(true, "CREATE (:Flag {type: 'on'})", "CREATE (:Flag {type: 'off'})", {}) YIELD value RETURN value | 类似编程中的 if-else |
| 批量提交 | CALL apoc.periodic.iterate(statement1, statement2, {batchSize:1000}) | 分批处理大数据 | CALL apoc.periodic.iterate("MATCH (n:Log) WHERE n.ts < 1700000000 RETURN n", "DETACH DELETE n", {batchSize:5000}) | 避免大事务 OOM;每批独立事务 |
| JSON 处理 | apoc.json.parse(jsonString) | 解析 JSON 字符串 | WITH '{"name":"Alice"}' AS json CALL apoc.json.parse(json) YIELD value CREATE (:Person {name: value.name}) | 返回 map 或 list |
5.3 图算法库(Graph Data Science Library)
| 操作/方法名称 | 语法/操作细节 | 用途 | 代码示例 | 注意事项 |
|---|
| 安装 GDS 库 | 下载 gds-*.jar 放入 plugins 目录,重启服务 | 启用图算法功能 | 1. 从 Neo4j 官网下载 GDS;2. 放入 plugins/;3. 无需额外配置(默认启用) | 仅企业版支持全部算法;社区版支持部分(如 PageRank、WCC) |
| 创建投影图 | CALL gds.graph.project('graphName', nodeLabel, relType) | 将子图加载到内存 | CALL gds.graph.project('myGraph', 'Person', 'FRIEND') | 投影图独立于原图,用于高效计算 |
| 运行 PageRank | CALL gds.pageRank.stream('graphName') YIELD nodeId, score | 计算节点重要性 | CALL gds.pageRank.stream('myGraph') YIELD nodeId, score RETURN gds.util.asNode(nodeId).name AS name, score ORDER BY score DESC | stream 模式不写回原图;write 模式可写属性 |
| 写回结果 | CALL gds.pageRank.write('graphName', {writeProperty: 'pagerank'}) | 将算法结果存回节点 | CALL gds.pageRank.write('myGraph', {writeProperty: 'score'}) | 需确保节点有写权限 |
| 查看投影图 | CALL gds.graph.list() | 列出所有内存图 | CALL gds.graph.list() | 显示图名、节点/关系数量、内存占用 |
| 释放投影图 | CALL gds.graph.drop('graphName') | 释放内存 | CALL gds.graph.drop('myGraph') | 长期不用的图应及时释放 |
| 弱连通分量(WCC) | CALL gds.wcc.stream('graphName') YIELD nodeId, componentId | 发现连通子图 | CALL gds.wcc.stream('myGraph') YIELD nodeId, componentId RETURN componentId, count(*) AS size ORDER BY size DESC | 适用于社区发现初步分析 |
5.4 性能调优与查询计划(EXPLAIN / PROFILE)
| 方法/操作名称 | 语法/操作细节 | 用途 | 代码示例 | 注意事项 |
|---|
| EXPLAIN | EXPLAIN MATCH (n:Person {name: 'Alice'}) RETURN n | 查看逻辑执行计划(不执行) | EXPLAIN MATCH (a)-[:FRIEND*2]->(b) RETURN b | 用于预估查询复杂度;显示运算符树 |
| PROFILE | PROFILE MATCH (n:Person {name: 'Alice'}) RETURN n | 查看实际执行计划(含性能数据) | PROFILE MATCH (p:Person)-[:WORKS_AT]->(c:Company) WHERE c.name = 'Neo4j' RETURN p.name | 显示每步的 DB Hits(数据库命中次数),值越低越好 |
| 查看 DB Hits | 在 PROFILE 输出中观察 | 衡量查询效率 | — | 高 DB Hits 通常因缺少索引或全图扫描 |
| 使用索引提示 | USING INDEX n:Label(property) | 强制使用索引(极少需要) | MATCH (n:Person {name: 'Alice'}) USING INDEX n:Person(name) RETURN n | 通常优化器自动选择;仅在误判时使用 |
| 避免笛卡尔积 | 确保 MATCH 有连接条件 | 防止爆炸性中间结果 | ❌ MATCH (a:Person), (b:Company) RETURN a, b / ✅ MATCH (a:Person)-[:WORKS_AT]->(b:Company) RETURN a, b | 笛卡尔积会导致 DB Hits 激增 |
| 参数化查询 | 使用 $param 而非拼接 | 提升计划缓存复用 | :param name => 'Alice'; MATCH (p:Person {name: $name}) RETURN p | 驱动程序中应使用参数化语句 |
| 清除计划缓存 | CALL db.clearQueryCaches() | 重置查询计划缓存 | CALL db.clearQueryCaches() | 用于测试不同索引效果时 |
第六章:Neo4j 应用开发
6.1 官方驱动(Java / Python / JavaScript 等)连接示例
| 驱动类型 | 语法/初始化方式 | 用途 | 代码示例 | 注意事项 |
|---|
| Java Driver | 使用 GraphDatabase.driver(uri, auth) | Java 应用连接 Neo4j | Driver driver = GraphDatabase.driver("bolt://localhost:7687", AuthTokens.basic("neo4j", "password")); Session session = driver.session(); Result result = session.run("MATCH (n) RETURN count(n)"); System.out.println(result.single().get(0).asLong()); session.close(); driver.close(); | 需添加 Maven 依赖:org.neo4j.driver / neo4j-java-driver / 5.18.0 |
| Python Driver | from neo4j import GraphDatabase | Python 应用连接 | driver = GraphDatabase.driver("bolt://localhost:7687", auth=("neo4j", "password")); with driver.session() as session: result = session.run("MATCH (n:Person) RETURN n.name"); for record in result: print(record["n.name"]); driver.close() | 安装:pip install neo4j;支持异步(AsyncGraphDatabase) |
| JavaScript Driver | const neo4j = require('neo4j-driver') | Node.js 应用连接 | const driver = neo4j.driver('bolt://localhost:7687', neo4j.auth.basic('neo4j', 'password')); const session = driver.session(); session.run('MATCH (n) RETURN count(n)').then(result => { console.log(result.records[0].get(0).toNumber()); session.close(); driver.close(); }); | 安装:npm install neo4j-driver;默认使用 Bolt 协议 |
| Go Driver | "github.com/neo4j/neo4j-go-driver/v5/neo4j" | Go 应用连接 | driver, err := neo4j.NewDriverWithContext("bolt://localhost:7687", neo4j.BasicAuth("neo4j", "password", "")); session := driver.NewSession(neo4j.SessionConfig{}); result, _ := session.Run("MATCH (n) RETURN count(n)", nil); record, _ := result.Single(); fmt.Println(record.Values[0]) | 需启用 Go modules;v5 对应 Neo4j 5.x |
6.2 REST API 调用方式(HTTP endpoint)
| 操作名称 | 请求方式与路径 | 用途 | 代码示例 | 注意事项 |
|---|
| 执行 Cypher(事务内) | POST /db/{database}/tx | 通过 HTTP 执行查询(推荐) | curl -X POST http://localhost:7474/db/neo4j/tx -H "Content-Type: application/json" -u neo4j:password -d '{"statements":[{"statement":"MATCH (n) RETURN count(n)"}]}' | 返回 JSON 结果;需处理事务 commit/rollback |
| 执行单条语句(简单模式) | POST /db/{database}/cypher | 快速执行单条查询(已弃用) | curl -X POST http://localhost:7474/db/neo4j/cypher -H "Content-Type: application/json" -u neo4j:password -d '{"query":"MATCH (n:Person) RETURN n.name"}' | Neo4j 4.0+ 已标记为 deprecated,建议使用 /tx 接口 |
| 获取节点(by ID) | GET /db/{database}/node/{id} | 按 ID 获取节点(旧版 REST) | curl -u neo4j:password http://localhost:7474/db/neo4j/node/123 | 仅适用于旧版(Neo4j 3.x);5.x 不推荐使用 |
| 列出数据库 | GET /db | 获取可用数据库列表 | curl -u neo4j:password http://localhost:7474/db | 返回 ["neo4j", "system"] 等 |
| 认证方式 | Basic Auth | 提供用户名密码 | 所有请求需带 -u user:pass 或 Authorization: Basic base64(user:pass) | 若 dbms.security.auth_enabled=false 可省略 |
| 错误处理 | 查看 HTTP 状态码 | 诊断失败原因 | 401: 认证失败;404: 路径错误;500: 查询异常 | 响应体中通常包含 error.message 字段 |
6.3 事务处理与批量操作
| 方法/操作名称 | 语法/操作细节 | 用途 | 代码示例(Python) | 注意事项 |
|---|
| 显式事务(begin/commit) | session.begin_transaction() | 控制多语句原子性 | with driver.session() as session: tx = session.begin_transaction(); try: tx.run("CREATE (:Order {id: 1})"); tx.run("CREATE (:Log {event: 'order_created'})"); tx.commit(); except: tx.rollback(); raise | 所有写操作应在事务中;默认自动提交(每条语句独立事务) |
| 自动提交事务(single) | session.execute_write(func) | 推荐的写操作封装 | def create_person(tx, name): tx.run("CREATE (:Person {name: $name})", name=name); with driver.session() as session: session.execute_write(create_person, "Alice") | 驱动自动处理事务 begin/commit/rollback |
| 批量插入(分批) | 循环 + 分批提交 | 避免大事务 OOM | users = [{"name": f"User{i}"} for i in range(10000)]; batch_size = 1000; for i in range(0, len(users), batch_size): batch = users[i:i+batch_size]; session.execute_write(lambda tx: tx.run("UNWIND $batch AS u CREATE (:Person {name: u.name})", batch=batch)) | 单事务建议不超过 1 万条;监控内存使用 |
| 参数化查询 | 使用 $param | 防止注入 & 提升性能 | session.run("MATCH (p:Person {name: $name}) RETURN p.age", name="Bob") | 所有用户输入必须参数化 |
| 读写分离 | execute_read / execute_write | 明确操作意图 | session.execute_read(lambda tx: tx.run("MATCH (n) RETURN count(n)")) | 有助于未来扩展(如读副本) |
6.4 与 Spring Boot / Django 等框架集成
| 框架 | 集成方式 | 用途 | 代码示例要点 | 注意事项 |
|---|
| Spring Boot | 使用 Spring Data Neo4j (SDN) | 对象图映射(OGM) | 1. 添加依赖:implementation 'org.springframework.boot:spring-boot-starter-data-neo4j';2. 配置 application.yml:spring.neo4j.uri=bolt://localhost:7687、spring.neo4j.authentication.username=neo4j、spring.neo4j.authentication.password=password;3. 定义实体:@Node public class Person { @Id @GeneratedValue private Long id; private String name; };4. Repository:interface PersonRepository extends Neo4jRepository<Person, Long> {} | SDN 6+ 基于官方驱动,不再依赖 OGM;支持 reactive |
| Django | 使用 neomodel 或 py2neo | Python ORM 风格操作 | 1. pip install neomodel;2. settings.py 中设置:NEO4J_URL = 'bolt://neo4j:password@localhost:7687';3. 定义模型:from neomodel import StructuredNode, StringProperty; class Person(StructuredNode): name = StringProperty();4. 使用:alice = Person(name='Alice').save() | neomodel 提供类似 Django ORM 的体验;py2neo 更底层 |
| Node.js + Express | 直接使用 JavaScript 驱动 | 构建 RESTful 服务 | const driver = neo4j.driver(...); app.get('/users', async (req, res) => { const session = driver.session(); try { const result = await session.run("MATCH (u:User) RETURN u.name"); res.json(result.records.map(r => r.get('u.name'))); } finally { await session.close(); } }); | 建议封装数据库访问为 service 层;注意连接池管理 |
| .NET Core | 使用 Neo4j.Driver NuGet 包 | C# 应用集成 | services.AddSingleton(sp => GraphDatabase.Driver("bolt://localhost:7687", AuthTokens.Basic("neo4j", "password"))); | 支持 async/await;需处理 IDisposable 生命周期 |
第七章:运维与高可用
7.1 备份与恢复(neo4j-admin dump / load)
| 操作名称 | 命令语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 全量备份(dump) | neo4j-admin database dump database --to=path | 将数据库导出为二进制 dump 文件 | ./bin/neo4j-admin database dump neo4j --to=/backups/neo4j-20260202.dump | 服务必须停止;仅支持单数据库备份;企业版支持在线备份(需额外许可) |
| 全量恢复(load) | neo4j-admin database load dump-file --database=name --force | 从 dump 文件恢复数据库 | ./bin/neo4j-admin database load /backups/neo4j-20260202.dump --database=neo4j --force | 服务必须停止;--force 覆盖现有数据;目标数据库名可不同于原名 |
| 备份多数据库 | 分别对每个数据库执行 dump | 备份系统中所有业务库 | ./bin/neo4j-admin database dump neo4j --to=/backups/neo4j.dump; ./bin/neo4j-admin database dump analytics --to=/backups/analytics.dump | Neo4j 4.0+ 支持多数据库;需逐个备份 |
| 验证 dump 文件 | file dump-file 或 head -c 100 dump-file | 确认文件非空且格式正确 | file /backups/neo4j.dump | 正常 dump 文件为 gzip 压缩格式,file 命令显示 “gzip compressed data” |
| 自动化备份脚本 | 编写 shell 脚本 + cron | 定期自动备份 | #!/bin/bash; NEO4J_HOME=/opt/neo4j; $NEO4J_HOME/bin/neo4j stop; $NEO4J_HOME/bin/neo4j-admin database dump neo4j --to=/backups/neo4j-$(date +%Y%m%d).dump; $NEO4J_HOME/bin/neo4j start | 停机备份影响可用性;生产环境应使用企业版在线备份或文件系统快照 |
| 清理旧备份 | find /backups -name "*.dump" -mtime +7 -delete | 保留最近7天备份 | find /backups -name "neo4j-*.dump" -mtime +30 -exec rm {} | 避免磁盘占满 |
7.2 集群部署(因果集群 Causal Clustering)
| 组件/配置项 | 说明/配置值 | 用途 | 配置示例(neo4j.conf) | 注意事项 |
|---|
| Core Server | 存储全量数据,参与共识(Raft) | 保证数据强一致性和持久性 | dbms.mode=CORE、dbms.cluster.discovery_type=SINGLE、dbms.cluster.initial_discovery_members=localhost:5000,localhost:5001,localhost:5002 | 至少 3 个 Core 节点(容忍 1 节点故障);奇数个更佳 |
| Read Replica | 只读副本,异步同步数据 | 扩展读吞吐,降低 Core 负载 | dbms.mode=READ_REPLICA、dbms.cluster.discovery_type=SINGLE、dbms.cluster.initial_discovery_members=localhost:5000 | 可水平扩展;不参与写共识;数据略有延迟 |
| Discovery Port | 5000(默认) | 节点间发现与通信 | causal_clustering.discovery_listen_address=:5000 | 需开放 TCP 端口;各节点 discovery_address 必须可达 |
| Transaction Port | 6000(默认) | Raft 日志复制 | causal_clustering.transaction_listen_address=:6000 | Core 节点间同步事务日志 |
| Raft Port | 7000(默认) | Raft 选举与心跳 | causal_clustering.raft_listen_address=:7000 | Core 节点间维持共识状态 |
| 初始成员列表 | 所有 Core 节点的 discovery 地址 | 集群启动引导 | dbms.cluster.initial_discovery_members=core1:5000,core2:5000,core3:5000 | 所有 Core 节点必须配置相同列表;Read Replica 也需配置 |
| 客户端连接地址 | 任一 Core 或 Read Replica 的 Bolt 地址 | 应用连接入口 | driver = GraphDatabase.driver("bolt://core1:7687", ...) | 写操作必须连 Core;读操作可连 Read Replica |
| 集群状态检查 | CALL dbms.cluster.overview() | 查看集群拓扑与角色 | CALL dbms.cluster.overview() YIELD id, role, groups RETURN * | 在任意 Core 节点执行;返回各节点状态 |
7.3 监控指标与 Prometheus 集成
| 操作/配置名称 | 配置/命令细节 | 用途 | 配置示例(neo4j.conf) | 注意事项 |
|---|
| 启用 Prometheus 端点 | 设置 metrics.prometheus.enabled=true | 暴露监控指标供 Prometheus 抓取 | metrics.prometheus.enabled=true、metrics.prometheus.endpoint=localhost:2004/metrics | 默认端口 2004;路径 /metrics |
| 自定义监听地址 | 修改 endpoint 地址 | 允许远程抓取 | metrics.prometheus.endpoint=0.0.0.0:2004/metrics | 生产环境需配合防火墙限制访问源 |
| 关键监控指标 | Neo4j 暴露的指标名称 | 用于告警与可视化 | neo4j_transactions_active、neo4j_page_cache_hits_ratio、neo4j_causal_clustering_core_role、jvm_memory_used_bytes | 完整列表见官方文档;建议监控事务队列、缓存命中率、集群角色 |
| 配置 Prometheus job | 在 prometheus.yml 中添加 | 抓取 Neo4j 指标 | scrape_configs: - job_name: 'neo4j' static_configs: - targets: ['core1:2004', 'core2:2004'] | 每个 Neo4j 实例需单独配置 target |
| Grafana 仪表盘 | 导入 Neo4j 官方 dashboard JSON | 可视化监控 | 使用 ID 11999(Neo4j Community Dashboard) | 需先配置 Prometheus 数据源 |
| 日志监控集成 | Filebeat / Fluentd 采集 logs/neo4j.log | 异常日志告警 | 配置 Filebeat 读取 logs/neo4j.log 并发送至 ELK | 关注 ERROR、WARN 级别日志 |
| 自定义指标(APOC) | CALL apoc.metrics.register(...) | 注册业务指标 | CALL apoc.metrics.register('user_count', 'MATCH (u:User) RETURN count(u)') | 需启用 apoc.metrics.enabled=true |
7.4 升级与版本迁移
| 操作名称 | 步骤/命令 | 用途 | 操作细节 | 注意事项 |
|---|
| 版本兼容性检查 | 查阅 Neo4j 官方升级文档 | 确认跨版本支持 | 例如:5.10 → 5.18 支持滚动升级;4.x → 5.x 需停机迁移 | 大版本升级(如 4→5)不兼容,需 dump/load |
| 小版本滚动升级(集群) | 逐个替换 Core 节点 | 零停机升级 | 1. 停止一个 Core 节点;2. 替换二进制文件;3. 启动新版本;4. 等待同步完成;5. 重复其他节点 | 仅适用于补丁或小版本(如 5.17 → 5.18);需保持协议兼容 |
| 大版本迁移(停机) | dump → 新实例 load | 跨主版本迁移 | 1. 在旧版停机后执行 dump;2. 安装新版 Neo4j;3. 执行 load 恢复数据;4. 启动并验证 | 必须停机;插件(APOC/GDS)需升级到对应版本 |
| 插件兼容性处理 | 下载匹配新版本的插件 | 避免启动失败 | 删除 plugins/apoc-5.10.jar,放入 apoc-5.18.jar | 插件版本必须与 Neo4j 主版本严格一致 |
| 配置文件迁移 | 对比新旧 neo4j.conf | 适配新参数 | 新版可能废弃旧参数(如 dbms.active_database → dbms.default_database) | 建议从新安装实例的默认 conf 文件开始,逐步合并自定义配置 |
| 回滚计划 | 保留旧版本备份 | 应对升级失败 | 1. 备份整个 NEO4J_HOME;2. 记录旧版本号;3. 测试回滚流程 | 升级前必须验证回滚可行性 |
| 数据验证 | 升级后运行校验查询 | 确保数据完整 | MATCH (n) RETURN count(n) AS nodeCount, count { (n)-[]->() } AS relCount | 与升级前统计值对比;检查关键业务实体 |