neo4j安装和使用

安装使用(windows)

  1. 下载
    官网找到社区版本Neo4j community

https://neo4j.com/product/community-edition/

注意: 3.* 对应java8, 5.*对应java21

  1. 环境变量配置

    新建NEO4J_HOME,并在变量值neo4j-community文件所在根目录
    PATH中新增bin文件夹配置%NEO4J_HOME%\bin

  2. 测试

cd neo4j-community-3.5.32\bin && neo4j.bat console

shell 复制代码
D:\neo4j-community-2025.12.1\bin>neo4j.bat console
Directories in use:
home:         D:\neo4j-community-2025.12.1
config:       D:\neo4j-community-2025.12.1\conf
logs:         D:\neo4j-community-2025.12.1\logs
plugins:      D:\neo4j-community-2025.12.1\plugins
import:       D:\neo4j-community-2025.12.1\import
data:         D:\neo4j-community-2025.12.1\data
certificates: D:\neo4j-community-2025.12.1\certificates
licenses:     D:\neo4j-community-2025.12.1\licenses
run:          D:\neo4j-community-2025.12.1\run
Starting Neo4j.
2026-01-19 13:43:01.202+0000 INFO  Logging config in use: File 'D:\neo4j-community-2025.12.1\conf\user-logs.xml'
2026-01-19 13:43:01.226+0000 INFO  Starting...
2026-01-19 13:43:01.726+0000 INFO  This instance is ServerId{168fd9ce} ()
2026-01-19 13:43:02.459+0000 INFO  ======== Neo4j 2025.12.1 ========
2026-01-19 13:43:03.648+0000 INFO  Anonymous Usage Data is being sent to Neo4j, see https://neo4j.com/docs/usage-data/
2026-01-19 13:43:04.121+0000 INFO  Bolt enabled on localhost:7687.
2026-01-19 13:43:04.658+0000 INFO  HTTP enabled on localhost:7474.
2026-01-19 13:43:04.658+0000 INFO  Remote interface available at http://localhost:7474/
2026-01-19 13:43:04.658+0000 INFO  id: 
2026-01-19 13:43:04.658+0000 INFO  name: system
2026-01-19 13:43:04.658+0000 INFO  creationDate: 2026-01-19T13:43:03.323Z
2026-01-19 13:43:04.658+0000 INFO  Started.

Neo4j 增删改查 - 入门版

一、就像跟朋友聊天一样简单

把 Neo4j 想象成一个人际关系笔记本

  • 节点 = 一个人(比如:张三)
  • 标签 = 这个人是谁(比如:朋友同事家人
  • 关系 = 怎么认识的(比如:认识喜欢同事

二、增(CREATE) - 添加信息

1. 添加一个人
cypher 复制代码
-- 添加一个朋友叫张三,28岁,北京人
CREATE (:朋友 {名字:'张三', 年龄:28, 城市:'北京'})
2. 添加多个人
cypher 复制代码
CREATE (:朋友 {名字:'李四', 年龄:25}),
       (:同事 {名字:'王五', 部门:'技术部'}),
       (:家人 {名字:'妈妈', 关系:'母亲'})
3. 添加关系(连接两个人)
cypher 复制代码
-- 先找到两个人
MATCH (张三:朋友 {名字:'张三'})
MATCH (李四:朋友 {名字:'李四'})

-- 让他们成为朋友(2010年认识的)
CREATE (张三)-[:认识 {认识时间:'2010年', 关系:'好朋友'}]->(李四)

一句话版本

cypher 复制代码
-- 直接创建两个人并连接
CREATE (:朋友 {名字:'小明'})-[:喜欢]->(:食物 {名字:'披萨'})

三、查(MATCH) - 查看信息

1. 查看所有人
cypher 复制代码
-- 查看所有朋友
MATCH (p:朋友) RETURN p

-- 查看朋友的名字和年龄
MATCH (p:朋友) RETURN p.名字, p.年龄
2. 按条件查找
cypher 复制代码
-- 找北京的朋友
MATCH (p:朋友 {城市:'北京'}) RETURN p.名字

-- 找年龄大于25的朋友
MATCH (p:朋友) WHERE p.年龄 > 25 RETURN p.名字, p.年龄
3. 查看关系
cypher 复制代码
-- 张三认识谁?
MATCH (张三:朋友 {名字:'张三'})-[关系]->(谁)
RETURN 谁.名字, 关系.认识时间

-- 谁和谁是朋友?
MATCH (a:朋友)-[r:认识]->(b:朋友)
RETURN a.名字, b.名字, r.关系

四、改(SET) - 修改信息

1. 修改属性
cypher 复制代码
-- 给张三添加电话号码
MATCH (p:朋友 {名字:'张三'})
SET p.电话 = '13800138000'

-- 修改张三的年龄
MATCH (p:朋友 {名字:'张三'})
SET p.年龄 = 29

-- 一次修改多个属性
MATCH (p:朋友 {名字:'张三'})
SET p.城市 = '上海',
    p.职业 = '工程师',
    p.更新时间 = '2023-01-01'
2. 添加标签
cypher 复制代码
-- 张三同时也是同事
MATCH (p {名字:'张三'})
SET p:同事

-- 有多个标签(既是朋友又是同事)
MATCH (p {名字:'李四'})
SET p:朋友:同事:VIP会员

五、删(DELETE) - 删除信息

1. 删除属性
cypher 复制代码
-- 删除张三的电话号码
MATCH (p:朋友 {名字:'张三'})
REMOVE p.电话

-- 删除年龄属性
MATCH (p:朋友 {名字:'张三'})
REMOVE p.年龄
2. 删除关系
cypher 复制代码
-- 删除张三和李四的"认识"关系
MATCH (张三:朋友 {名字:'张三'})-[r:认识]->(李四:朋友 {名字:'李四'})
DELETE r
3. 删除节点(小心!)
cypher 复制代码
-- 删除张三这个人
MATCH (p:朋友 {名字:'张三'})
DELETE p

-- 先删除关系,再删除节点(安全做法)
MATCH (p:朋友 {名字:'张三'})-[r]-()
DELETE r, p

六、完整例子:朋友圈管理

cypher 复制代码
-- 1. 添加朋友
CREATE (:朋友 {名字:'小明', 年龄:25, 城市:'北京'}),
       (:朋友 {名字:'小红', 年龄:23, 城市:'上海'}),
       (:朋友 {名字:'小刚', 年龄:28, 城市:'广州'})

-- 2. 建立朋友关系
MATCH (小明:朋友 {名字:'小明'})
MATCH (小红:朋友 {名字:'小红'})
CREATE (小明)-[:认识 {时间:'2022年', 怎么认识:'大学同学'}]->(小红)

-- 3. 查看所有朋友
MATCH (p:朋友) RETURN p.名字, p.年龄, p.城市

-- 4. 小明搬家到深圳
MATCH (p:朋友 {名字:'小明'})
SET p.城市 = '深圳'

-- 5. 删除小刚(他不玩朋友圈了)
MATCH (p:朋友 {名字:'小刚'})
DELETE p

-- 6. 查看剩余的朋友
MATCH (p:朋友) RETURN p.名字

七、需要记住的公式

复制代码
1. 增加:CREATE (标签:名字 {属性:值})
2. 查询:MATCH (条件) RETURN 显示什么
3. 修改:MATCH (条件) SET 属性=新值
4. 删除:MATCH (条件) DELETE 什么

八、千万要注意!

⚠️ 删除前先查询
cypher 复制代码
-- 错误:直接删除会删掉所有!
DELETE p  -- 别这样!

-- 正确:先看看要删什么
MATCH (p:朋友) RETURN p  -- 先查看
MATCH (p:朋友 {名字:'张三'}) DELETE p  -- 再删除
⚠️ 关系不能单独存在
cypher 复制代码
-- 错误:有关系的节点不能直接删
MATCH (p:朋友 {名字:'小明'}) DELETE p  -- 会报错!

-- 正确:先删关系,再删节点
MATCH (p:朋友 {名字:'小明'})-[r]-()
DELETE r, p

九、最常用命令总结

想做什么 命令模板
添加一个人 CREATE (:标签 {名字:'张三'})
找人 MATCH (p:标签 {名字:'张三'}) RETURN p
修改信息 MATCH (p {名字:'张三'}) SET p.新属性='值'
删除人 MATCH (p {名字:'张三'}) DELETE p
建立关系 CREATE (张三)-[:关系]->(李四)
删除关系 MATCH ()-[r:关系]->() DELETE r

简单练习

打开 Neo4j Browser(网页界面),依次输入:

cypher 复制代码
-- 1. 创建你的第一个节点
CREATE (:我 {名字:'[你的名字]', 爱好:'编程'})

-- 2. 查看是否创建成功
MATCH (n:我) RETURN n

-- 3. 添加更多信息
MATCH (n:我)
SET n.年龄 = 20,
    n.城市 = '北京'

-- 4. 再查看一次
MATCH (n:我) RETURN n

-- 5. 创建朋友
CREATE (:朋友 {名字:'AI助手', 类型:'人工智能'})

-- 6. 建立关系
MATCH (我:我), (朋友:朋友 {名字:'AI助手'})
CREATE (我)-[:使用]->(朋友)

-- 7. 查看整个关系图
MATCH (a)-[r]->(b)
RETURN a, r, b

就是这样!你已经学会了 Neo4j 的基本操作 🎉

记住:CREATE 添加,MATCH 查找,SET 修改,DELETE 删除

Neo4j 关系的增删改查 - 超详细版

一、关系的核心概念

简单比喻:
复制代码
节点 = 两个人(张三、李四)
关系 = 他们之间的连接线(认识、同事、朋友)
关系属性 = 线上的标签(认识多久、关系多好)

二、增(CREATE)关系

1. 基础创建:连接两个现有节点
cypher 复制代码
-- 先找到两个节点
MATCH (张三:人 {名字:'张三'})
MATCH (李四:人 {名字:'李四'})

-- 创建关系(A 认识 B)
CREATE (张三)-[:认识]->(李四)

-- 创建双向关系(互相认识)
CREATE (张三)-[:认识]->(李四)
CREATE (李四)-[:认识]->(张三)

-- 或者用更简洁的方式
CREATE (张三)-[:认识]->(李四),
       (李四)-[:认识]->(张三)
2. 创建时添加属性
cypher 复制代码
-- 创建带详细信息的"认识"关系
CREATE (张三)-[:认识 {
  认识时间: '2020-01-01',
  地点: '北京',
  介绍人: '王五',
  亲密程度: 7
}]->(李四)
3. 一次性创建节点和关系
cypher 复制代码
-- 最常用的方式!
CREATE (张三:人 {名字:'张三'})
       -[:同事 {
         部门: '技术部',
         共事开始: '2021-03-15'
       }]->
       (李四:人 {名字:'李四'})

-- 创建三角形关系网
CREATE (小明:学生 {名字:'小明'}),
       (小红:学生 {名字:'小红'}),
       (小刚:学生 {名字:'小刚'}),
       (小明)-[:同班]->(小红),
       (小红)-[:同班]->(小刚),
       (小刚)-[:同桌]->(小明)
4. 创建不同类型的关系
cypher 复制代码
-- 一个人可以有多种关系
MATCH (张三:人 {名字:'张三'})
MATCH (公司:公司 {名称:'阿里巴巴'})

-- 同时创建工作和朋友关系
CREATE (张三)-[:工作于 {
  职位: '工程师',
  入职时间: '2020-01-01',
  工资: 25000
}]->(公司),

(张三)-[:朋友]->(:人 {名字:'王五'}),

(张三)-[:喜欢]->(:爱好 {名称:'篮球'})

三、查(MATCH)关系

1. 查找特定关系
cypher 复制代码
-- 查找所有"认识"关系
MATCH ()-[r:认识]->()
RETURN r

-- 查找具体的两个人之间的关系
MATCH (张三:人 {名字:'张三'})-[r]-(李四:人 {名字:'李四'})
RETURN type(r) as 关系类型, r as 关系详情
2. 查找关系的属性
cypher 复制代码
-- 查看关系的具体信息
MATCH (:人 {名字:'张三'})-[r:认识]->(:人 {名字:'李四'})
RETURN r.认识时间, r.地点, r.亲密程度

-- 按关系属性筛选
MATCH ()-[r:认识]->()
WHERE r.亲密程度 > 5 AND r.认识时间 > '2021-01-01'
RETURN r
3. 查找关系路径
cypher 复制代码
-- 找通过朋友认识的人(朋友的朋友)
MATCH (我:人 {名字:'张三'})-[:认识]->(朋友)-[:认识]->(朋友的朋友)
RETURN 朋友.名字 as 直接朋友, 朋友的朋友.名字 as 间接朋友

-- 查找多层关系(最多3层)
MATCH (我:人 {名字:'张三'})-[:认识*1..3]->(陌生人)
RETURN 陌生人.名字, count(*) as 关系层数
4. 查找关系统计
cypher 复制代码
-- 谁的朋友最多?
MATCH (p:人)-[:认识]->(朋友)
RETURN p.名字, count(朋友) as 朋友数量
ORDER BY 朋友数量 DESC

-- 关系的平均亲密程度
MATCH ()-[r:认识]->()
RETURN avg(r.亲密程度) as 平均亲密程度

四、改(SET)关系

1. 修改关系属性
cypher 复制代码
-- 增加或修改关系属性
MATCH (张三:人 {名字:'张三'})-[r:认识]->(李四:人 {名字:'李四'})
SET r.亲密程度 = 8,
    r.最近联系 = date(),
    r.备注 = '很好的朋友'

-- 增加新属性
MATCH (:人 {名字:'张三'})-[r:同事]->(:人 {名字:'李四'})
SET r.项目合作 = '支付宝项目',
    r.配合评分 = 9.5
2. 修改关系类型(不能直接改,需要重新创建)
cypher 复制代码
-- 错误:不能直接修改关系类型
-- MATCH ()-[r:认识]->() SET r:朋友  -- 不行!

-- 正确做法:先删除旧关系,再创建新关系
MATCH (张三:人 {名字:'张三'})-[r:认识]->(李四:人 {名字:'李四'})

-- 保存旧属性
WITH 张三, 李四, r.认识时间 as 旧时间, r.地点 as 旧地点

-- 删除旧关系
DELETE r

-- 创建新关系并保留旧属性
CREATE (张三)-[:朋友 {
  成为朋友时间: 旧时间,
  认识地点: 旧地点,
  好友等级: 'A级'
}]->(李四)
3. 批量修改关系
cypher 复制代码
-- 给所有"同事"关系添加公司信息
MATCH ()-[r:同事]->()
WHERE r.公司 IS NULL
SET r.公司 = '默认公司',
    r.更新时间 = timestamp()

-- 修改符合条件的多个关系
MATCH (a)-[r:交易]->(b)
WHERE r.金额 > 10000
SET r.状态 = '大额交易',
    r.需要审核 = true,
    r.审核人 = '财务部'

五、删(DELETE)关系

1. 删除特定关系
cypher 复制代码
-- 删除两个人之间的"认识"关系
MATCH (张三:人 {名字:'张三'})-[r:认识]->(李四:人 {名字:'李四'})
DELETE r

-- 删除特定属性的关系
MATCH ()-[r:认识]->()
WHERE r.亲密程度 < 3  -- 删除不亲密的关系
DELETE r
2. 删除某人所有的某种关系
cypher 复制代码
-- 删除张三所有的"认识"关系
MATCH (张三:人 {名字:'张三'})-[r:认识]-()
DELETE r

-- 删除张三所有的关系(不管什么类型)
MATCH (张三:人 {名字:'张三'})-[r]-()
DELETE r
3. 批量删除关系
cypher 复制代码
-- 删除所有过期的"临时"关系
MATCH ()-[r:临时关系]->()
WHERE r.过期时间 < date()
DELETE r

-- 删除所有空的关系(没有属性)
MATCH ()-[r]->()
WHERE r IS NOT NULL AND keys(r) = []
DELETE r
4. 安全删除(先检查再删除)
cypher 复制代码
-- 安全做法:先看看要删什么
MATCH (张三:人 {名字:'张三'})-[r]->()
RETURN type(r) as 关系类型, count(r) as 数量
-- 确认无误后再删

-- 或者用事务方式
BEGIN
MATCH (张三:人 {名字:'张三'})-[r:认识]->()
DELETE r
RETURN count(r) as 已删除数量
COMMIT

六、综合实例:社交网络管理

cypher 复制代码
-- 1. 创建社交网络
CREATE (张三:用户 {名字:'张三', 年龄:28}),
       (李四:用户 {名字:'李四', 年龄:25}),
       (王五:用户 {名字:'王五', 年龄:30}),
       (公司:企业 {名称:'腾讯'}),

-- 建立关系
(张三)-[:关注 {时间:'2023-01-01'}]->(李四),
(张三)-[:关注 {时间:'2023-02-01'}]->(王五),
(李四)-[:关注 {时间:'2023-01-15'}]->(张三),
(张三)-[:工作于 {职位:'工程师'}]->(公司),

-- 2. 查询张三的关注关系
MATCH (张三:用户 {名字:'张三'})-[r:关注]->(被关注)
RETURN 被关注.名字, r.时间
ORDER BY r.时间 DESC

-- 3. 修改关系:张三取消对李四的关注
MATCH (张三:用户 {名字:'张三'})-[r:关注]->(李四:用户 {名字:'李四'})
DELETE r
RETURN '已取消关注'

-- 4. 添加新关系:张三关注了新朋友
MATCH (张三:用户 {名字:'张三'})
MATCH (新人:用户 {名字:'赵六'})
CREATE (张三)-[:关注 {
  时间: date(),
  来源: '系统推荐',
  兴趣匹配度: 85
}]->(新人)

-- 5. 修改关系属性:更新关注时间
MATCH (张三:用户 {名字:'张三'})-[r:关注]->(王五:用户 {名字:'王五'})
SET r.最近互动 = datetime(),
    r.互动次数 = COALESCE(r.互动次数, 0) + 1

-- 6. 分析关系网络
-- 谁被最多人关注?
MATCH (用户:用户)<-[r:关注]-()
RETURN 用户.名字, count(r) as 粉丝数
ORDER BY 粉丝数 DESC

-- 互相关注的好友
MATCH (a:用户)-[:关注]->(b:用户),
      (b:用户)-[:关注]->(a:用户)
RETURN a.名字 as 用户A, b.名字 as 用户B

七、高级关系操作

1. 关系方向操作
cypher 复制代码
-- 忽略方向查询(A和B有关系,不管谁指向谁)
MATCH (张三:人)-[:认识]-(李四:人)
RETURN 张三.名字, 李四.名字

-- 只查询指向自己的关系
MATCH (张三:人)<-[r:认识]-(别人)
RETURN 别人.名字 as 谁关注我, r.时间

-- 只查询自己指向别人的关系
MATCH (张三:人)-[r:认识]->(别人)
RETURN 别人.名字 as 我关注谁, r.时间
2. 关系路径查找
cypher 复制代码
-- 找到张三到王五的最短路径
MATCH path = shortestPath(
  (张三:人 {名字:'张三'})-[:认识|同事|朋友*]-(王五:人 {名字:'王五'})
)
RETURN path, length(path) as 关系层数

-- 找到所有可能的联系路径(最多3步)
MATCH path = (张三:人 {名字:'张三'})-[:认识*1..3]-(陌生人)
RETURN 陌生人.名字, [node in nodes(path) | node.名字] as 路径
3. 关系聚合查询
cypher 复制代码
-- 统计关系的各种信息
MATCH (:人)-[r:交易]->(:商家)
RETURN 
  count(r) as 总交易数,
  sum(r.金额) as 总金额,
  avg(r.金额) as 平均金额,
  max(r.金额) as 最大交易,
  min(r.金额) as 最小交易

八、重要注意事项

⚠️ 关系不能单独存在
cypher 复制代码
-- 错误:删除节点时不删除关系
MATCH (n:人 {名字:'张三'})
DELETE n  -- 如果张三有关系,会报错!

-- 正确:先删关系,再删节点
MATCH (n:人 {名字:'张三'})-[r]-()
DELETE r, n
⚠️ 关系必须有方向
cypher 复制代码
-- 创建时必须指定方向
CREATE (A)-[:关系]->(B)  -- 正确
CREATE (A)-[:关系]-(B)   -- 错误!少了一个箭头

-- 但查询时可以忽略方向
MATCH (A)-[:关系]-(B)    -- 查询时这样可以
⚠️ 关系类型不能有空格
cypher 复制代码
-- 错误
CREATE ()-[:好友 关系]->()  -- 有空格

-- 正确
CREATE ()-[:好友关系]->()   -- 无空格
CREATE ()-[:好友_关系]->()  -- 用下划线

九、实战练习

cypher 复制代码
-- 练习:家庭关系管理
-- 1. 创建家庭成员
CREATE (爷爷:家人 {名字:'爷爷', 辈分:'祖辈'}),
       (爸爸:家人 {名字:'爸爸', 辈分:'父辈'}),
       (我:家人 {名字:'小明', 辈分:'子辈'}),
       (儿子:家人 {名字:'小亮', 辈分:'孙辈'})

-- 2. 建立家庭关系
CREATE (爷爷)-[:父亲]->(爸爸),
       (爸爸)-[:父亲]->(我),
       (我)-[:父亲]->(儿子),
       (爷爷)-[:祖父]->(我),
       (爷爷)-[:曾祖父]->(儿子)

-- 3. 查询:我的所有祖先
MATCH (我:家人 {名字:'小明'})<-[:父亲*]-(祖先)
RETURN 祖先.名字, 祖先.辈分

-- 4. 修改:添加关系属性
MATCH (爸爸:家人 {名字:'爸爸'})-[r:父亲]->(我:家人 {名字:'小明'})
SET r.出生年份 = 1980,
    r.教育程度 = '大学'

-- 5. 删除:如果关系录入错误
MATCH (某人)-[r:父亲]->(儿子:家人 {名字:'小亮'})
WHERE 某人.名字 = '爸爸'  -- 发现录错了,爸爸不是小亮的父亲
DELETE r

-- 6. 重新建立正确关系
MATCH (我:家人 {名字:'小明'})
MATCH (儿子:家人 {名字:'小亮'})
CREATE (我)-[:父亲 {
  关系确认: true,
  确认时间: date()
}]->(儿子)

十、快速参考表

操作 命令 说明
创建关系 CREATE (A)-[:类型]->(B) 最基本的创建
带属性创建 CREATE (A)-[:类型 {属性:值}]->(B) 创建时添加属性
查找关系 MATCH (A)-[r:类型]->(B) 给关系起名 r
查找关系属性 MATCH ()-[r:类型]->() RETURN r.属性 返回属性值
修改关系 MATCH ()-[r:类型]->() SET r.属性=值 修改属性
删除关系 MATCH ()-[r:类型]->() DELETE r 删除关系
查找路径 MATCH path = ()-[:类型*]-() RETURN path 查找连接路径
统计关系 MATCH ()-[r:类型]->() RETURN count(r) 统计数量

记住:关系就是节点之间的线,可以带属性、有方向、可以查询和修改!

复制代码
图 = 节点(信息点) + 边(连接线)

让我用更直观的方式展示你的理解:

🌟 你的理解 vs 技术术语
你的说法 技术术语 简单比喻
节点信息 节点属性(Properties) 人的身份证信息
边信息 关系属性(Relationship Properties) 两人关系的详情
节点和边构成图 属性图模型 人际关系网

用现实例子验证你的理解:

📍 社交网络例子:
cypher 复制代码
-- 节点(人)的信息
CREATE (:人 {
  姓名: '张三',      -- 节点信息
  年龄: 28,
  职业: '工程师'
})

-- 边(关系)的信息
CREATE (:人 {姓名: '张三'})
      -[:认识 {       -- 边信息开始
        认识时间: '2020-01-01',
        认识地点: '北京',
        关系强度: 8
      }]->           -- 边信息结束
      (:人 {姓名: '李四'})

为什么这个理解很重要?

1. 灵活性极高
cypher 复制代码
-- 同一种"人"节点,信息可以完全不同
CREATE (:人 {姓名: '张三', 年龄: 28})           -- 有年龄
CREATE (:人 {姓名: '李四', 城市: '北京'})        -- 没年龄,有城市
CREATE (:人 {姓名: '王五'})                    -- 只有姓名

-- 同一种"认识"关系,信息也可以不同
CREATE ()-[:认识 {时间: '2020年'}]->()          -- 有时间
CREATE ()-[:认识 {方式: '同事介绍'}]->()         -- 有方式
CREATE ()-[:认识]->()                         -- 只有关系,没额外信息
2. 查询就像"看图说话"
cypher 复制代码
-- "找到所有在北京认识的人"
MATCH (我:人)-[边:认识]->(别人:人)
WHERE 边.认识地点 = '北京'
RETURN 别人.姓名, 边.认识时间

-- 这就像:
-- 1. 找到"我"这个节点
-- 2. 找到从"我"出发的"认识"边
-- 3. 查看这条边的"认识地点"信息
-- 4. 找到边连接的"别人"节点
3. 修改就是更新"信息标签"
cypher 复制代码
-- 更新节点信息
MATCH (节点:人 {姓名: '张三'})
SET 节点.年龄 = 29           -- 更新节点的身份证信息
SET 节点.已婚 = true

-- 更新边信息  
MATCH (张三:人)-[边:认识]->(李四:人)
SET 边.最近联系 = date()     -- 更新关系的记录本
SET 边.关系强度 = 边.关系强度 + 1

用这个理解解决实际问题:

场景:电商推荐系统
cypher 复制代码
-- 1. 节点:用户和商品(都是信息点)
CREATE (:用户 {
  用户ID: 'U001',
  姓名: '张三',
  偏好: ['数码', '运动']
})

CREATE (:商品 {
  商品ID: 'P001',
  名称: 'iPhone',
  类别: '数码',
  价格: 6999
})

-- 2. 边:购买关系(连接信息)
CREATE (:用户 {用户ID: 'U001'})
      -[:购买 {
        时间: '2023-10-01',
        金额: 6999,
        评分: 5,
        评价: '很好用'
      }]->
      (:商品 {商品ID: 'P001'})

-- 3. 查询:基于图的推荐
-- "找买了数码产品的人还买了什么?"
MATCH (张三:用户 {用户ID: 'U001'})-[:购买]->(数码:商品 {类别: '数码'})
      <-[:购买]-(其他用户:用户)
      -[:购买]->(推荐商品:商品)
WHERE 推荐商品.类别 IN 张三.偏好
RETURN 推荐商品.名称, count(*) as 推荐度
ORDER BY 推荐度 DESC

几个关键洞察:

🔑 节点 = 实体
  • 可以是:人、商品、地点、事件
  • 每个节点有自己的"身份证信息"
🔑 边 = 关系
  • 连接两个节点
  • 有自己的"关系描述信息"
  • 有方向:A → B 和 B → A 是不同的
🔑 图的力量
cypher 复制代码
-- 传统数据库需要多次查询
-- 1. 查用户表
-- 2. 查订单表  
-- 3. 查商品表
-- 4. 查评价表

-- Neo4j一次查询搞定
MATCH (用户)-[购买:购买]->(商品)
      <-[浏览:浏览]-(用户)
      -[搜索:搜索]->(相关)
RETURN 用户, 购买, 商品, 浏览, 搜索, 相关
-- 一次返回所有相关信息!

可视化你的理解:

复制代码
       节点信息                       边信息                       节点信息
    ┌─────────────┐          ┌──────────────────┐          ┌─────────────┐
    │   张三      │          │      认识        │          │   李四      │
    │  年龄:28    │─────────▶│  时间:2020年    │─────────▶│  年龄:25    │
    │  城市:北京  │          │  地点:咖啡馆    │          │  城市:上海  │
    └─────────────┘          └──────────────────┘          └─────────────┘
         ↑                          ↑                          ↑
      信息点                     连接信息                    信息点

最后,记住这个核心公式:

复制代码
图 = ∑(节点 + 节点信息) + ∑(边 + 边信息)

Neo4j擅长处理:

  • 社交网络(谁认识谁)
  • 推荐系统(买了A的人也买了B)
  • 欺诈检测(异常关系网络)
  • 知识图谱(概念之间的关系)

核心特性

一、边的方向:可以是单向或双向

1. 单向边(有向边) - 大部分情况
cypher 复制代码
-- A → B(A认识B,但B不一定认识A)
CREATE (:人 {名字:'张三'})-[:认识]->(:人 {名字:'李四'})

-- 这意味着:
-- 张三 认识 → 李四 ✓
-- 李四 认识 → 张三 ✗(除非另有创建)

-- 现实例子:
-- 微博关注:我关注你,你不一定关注我
-- 转账:我转钱给你
-- 点赞:我给帖子点赞
2. 双向边(无向边) - 需要明确创建
cypher 复制代码
-- Neo4j没有真正的"双向边",需要创建两条相反方向的边
CREATE (张三:人 {名字:'张三'}),
       (李四:人 {名字:'李四'}),
       (张三)-[:朋友]->(李四),
       (李四)-[:朋友]->(张三)

-- 或者用双向箭头(实际上是创建两条边)
CREATE (张三)-[:朋友]-(李四)  -- 这会在内部创建两条方向相反的边

-- 现实例子:
-- 微信好友:需要双方同意
-- 婚姻关系:双方互为配偶
-- 同事关系:在同一公司工作
3. 方向查询的灵活性
cypher 复制代码
-- 1. 查询时指定方向
MATCH (张三:人 {名字:'张三'})-->()  -- 只找张三指向的
RETURN count(*)

MATCH (张三:人 {名字:'张三'})<--()  -- 只找指向张三的  
RETURN count(*)

-- 2. 查询时忽略方向
MATCH (张三:人 {名字:'张三'})--()   -- 找到所有相连的(不分方向)
RETURN count(*)

-- 3. 查询双向关系(互相的)
MATCH (a:人)-[:朋友]->(b:人),
      (b:人)-[:朋友]->(a:人)
RETURN a.名字, b.名字

二、环(Cycles):完全可以存在!

1. 什么是环?
复制代码
A → B → C → A  形成一个循环
2. 简单环示例
cypher 复制代码
-- 创建三角形环
CREATE (张三:人 {名字:'张三'}),
       (李四:人 {名字:'李四'}),
       (王五:人 {名字:'王五'}),
       (张三)-[:认识]->(李四),
       (李四)-[:认识]->(王五),
       (王五)-[:认识]->(张三)  -- 形成环!

-- 查询这个环
MATCH path = (a:人)-[:认识*3]->(a)  -- 走3步回到自己
RETURN [node in nodes(path) | node.名字] as 环上的人
3. 自环(Self-loop) - 自己连接自己
cypher 复制代码
-- 节点连接到自身
CREATE (张三:人 {名字:'张三'})
CREATE (张三)-[:自我提醒 {内容:'记得吃药'}]->(张三)

-- 现实例子:
-- 日程提醒:给自己设置提醒
-- 自我评价:对自己的评分
-- 自引用:比如"本文参考了本文"

-- 查询自环
MATCH (n)-[r]->(n)  -- 起点和终点是同一个节点
RETURN n.名字, type(r), r.内容
4. 实际中的环
cypher 复制代码
-- 资金循环(洗钱检测)
CREATE (公司A:公司)-[:转账 {金额:100万}]->(公司B),
       (公司B)-[:转账 {金额:100万}]->(公司C),
       (公司C)-[:转账 {金额:100万}]->(公司A)  -- 钱转了一圈回来了!

-- 家族近亲结婚环
CREATE (爷爷)-[:父亲]->(爸爸),
       (爸爸)-[:父亲]->(儿子),
       (儿子)-[:婚姻]->(姑姑),  -- 假设姑姑是爷爷的女儿
       (姑姑)-[:父亲]->(爷爷)   -- 形成环!

三、方向与环的组合示例

场景:微博关注网络
cypher 复制代码
-- 创建用户和关注关系
CREATE (张三:用户 {名字:'张三'}),
       (李四:用户 {名字:'李四'}),
       (王五:用户 {名字:'王五'}),
       (赵六:用户 {名字:'赵六'}),
       
       -- 单向关注
       (张三)-[:关注]->(李四),   -- 张关注李
       (张三)-[:关注]->(王五),   -- 张关注王
       (李四)-[:关注]->(王五),   -- 李关注王
       
       -- 双向关注(互相关注)
       (王五)-[:关注]->(张三),   -- 王也关注张
       
       -- 环:关注链条回到起点
       (王五)-[:关注]->(赵六),   -- 王关注赵
       (赵六)-[:关注]->(张三)    -- 赵关注张,形成环:张→王→赵→张

-- 查询:谁关注我但我没关注TA(单向)
MATCH (我:用户 {名字:'张三'})<-[被关注:关注]-别人
WHERE NOT (我)-[:关注]->(别人)
RETURN 别人.名字 as 粉丝, '单向关注' as 关系类型

-- 查询:互相关注(双向)
MATCH (a:用户)-[:关注]->(b:用户)
WHERE (b)-[:关注]->(a)
RETURN a.名字 as 用户A, b.名字 as 用户B, '互相关注' as 关系类型

-- 查询:发现关注环
MATCH path = (a:用户)-[:关注*3]->(a)  -- 3步回到自己
RETURN [node in nodes(path) | node.名字] as 关注环

四、方向的重要性

1. 方向影响查询结果
cypher 复制代码
-- 准备数据
CREATE (北京:城市)-[:连接 {距离:100}]->(天津),
       (天津)-[:连接 {距离:150}]->(上海)

-- 查询1:从北京能到哪?(考虑方向)
MATCH (北京:城市 {名字:'北京'})-[:连接*]->(目的地)
RETURN 目的地.名字  -- 结果:天津、上海

-- 查询2:能到北京的城市?(反向)
MATCH (出发地)-[:连接*]->(北京:城市 {名字:'北京'})
RETURN 出发地.名字  -- 结果:没有!因为路是单向的
2. 方向表示因果关系
cypher 复制代码
-- 事件链:A导致B,B导致C
CREATE (事件A:事件)-[:导致]->(事件B),
       (事件B)-[:导致]->(事件C)

-- 查找根本原因
MATCH (原因)-[:导致*]->(结果:事件 {名字:'事件C'})
RETURN 原因.名字  -- 可以找到事件A是根本原因

-- 如果边没有方向,就分不清因果了!
3. 环的特殊处理
cypher 复制代码
-- 检测无限循环
MATCH path = (a)-[:引用*]->(a)  -- 文档互相引用形成环
RETURN path LIMIT 1

-- 避免查询死循环
-- 设置最大深度
MATCH (a)-[:朋友*1..10]->(b)  -- 最多10层,避免无限循环

-- 环在现实中的意义:
-- ✅ 好的环:推荐系统的"看了又看"
-- ❌ 坏的环:死锁、无限递归

五、实际应用场景

场景1:交通网络(单向很重要!)
cypher 复制代码
-- 单行道系统
CREATE (路口A)-[:单行道 {方向:'东向西'}]->(路口B)
-- 不能从B直接到A,需要绕路

-- 环岛(环形路)
CREATE (入口)-[:进入]->(环岛),
       (环岛)-[:出口 {到:'A路口'}]->(路口A),
       (环岛)-[:出口 {到:'B路口'}]->(路口B),
       (环岛)-[:继续]->(环岛)  -- 可以在环岛里转圈!
场景2:工作流审批(有向无环图DAG)
cypher 复制代码
-- 审批流程不能有环,否则会死循环
CREATE (申请)-[:提交给]->(经理审批),
       (经理审批)-[:通过给]->(总监审批),
       (总监审批)-[:通过给]->(财务审批),
       (财务审批)-[:完成给]->(申请)  -- 完成,不是新的审批
       
-- 检测是否有非法环(审批回到之前的人)
MATCH path = (a:审批)-[:提交给|通过给*]->(a)
RETURN path  -- 如果有结果,说明流程设计有问题
场景3:社交网络的"六度空间"
cypher 复制代码
-- 查找两个人之间的联系路径(可能包含环)
MATCH path = shortestPath(
  (我:用户 {名字:'张三'})-[:认识|同事|同学*1..6]-(名人:用户 {名字:'马云'})
)
-- 可能路径:张→李→王→...→马云
-- 这个路径里可能有环(比如通过同一个圈子)

六、重要总结

✅ 边的方向性:
  1. 默认是单向的:A → B ≠ B → A
  2. 双向需要两条边:A → B 且 B → A
  3. 查询时可以忽略方向:A -- B(找所有连接)
  4. 现实意义:关注、转账、依赖等都有方向
✅ 环的存在性:
  1. 完全可以有环:A → B → C → A
  2. 自环也允许:A → A(自己连接自己)
  3. 环的用途:循环依赖、环形流程、社交圈子
  4. 需要注意:查询时要避免无限循环
⚠️ 使用建议:
cypher 复制代码
-- 1. 明确边的方向意义
CREATE ()-[:转账 {from: A, to: B}]->()  -- 明确谁转给谁

-- 2. 环检测查询
MATCH path = ()-[:依赖*]->() 
WHERE length(path) > 10  -- 防止太长的环
RETURN path

-- 3. 双向关系的处理
-- 如果经常需要查询"互相"关系,考虑:
CREATE ()-[:好友 {双向: true}]->()  -- 用属性标记
📊 可视化理解:
复制代码
单向链:          双向关系:          环:
A → B → C        A ↔ B             A → B
                                 ↖    ↓
                                   C ← D

自环:            复杂环:
   ↻              A → B → C
   A              ↑       ↓
                  D ← E ← F

记住:Neo4j的灵活性让你可以自由地:

  • 创建单向或双向的关系
  • 构建复杂的环状结构
  • 根据业务需求设计图模式

这就是图数据库的强大之处!它更贴近真实世界的关系网络。🌐

Neo4j 索引详解 - 从入门到实战

一、索引的核心作用:加速查询

cypher 复制代码
-- 没有索引:Neo4j要扫描所有节点
MATCH (p:Person) WHERE p.name = '张三'  -- 慢!要查所有人

-- 有索引:Neo4j直接跳到目标位置
MATCH (p:Person) WHERE p.name = '张三'  -- 快!用索引查找

二、索引类型速览

索引类型 用途 创建命令
单属性索引 加速单个属性查询 CREATE INDEX FOR (n:Label) ON (n.property)
复合索引 加速多属性组合查询 CREATE INDEX FOR (n:Label) ON (n.p1, n.p2)
全文索引 文本模糊搜索 CREATE FULLTEXT INDEX ...
文本索引 字符串前缀匹配 CREATE TEXT INDEX ...

三、实战:一步一步创建索引

1. 准备工作:创建测试数据
cypher 复制代码
-- 先创建一些数据(没有索引)
CREATE (:Person {name: '张三', age: 25, city: '北京'}),
       (:Person {name: '李四', age: 30, city: '上海'}),
       (:Person {name: '王五', age: 28, city: '广州'}),
       (:Person {name: '赵六', age: 35, city: '北京'}),
       (:Person {name: '钱七', age: 40, city: '上海'})

-- 创建产品数据
CREATE (:Product {sku: 'P001', name: 'iPhone 15', price: 6999}),
       (:Product {sku: 'P002', name: '华为Mate 60', price: 5999}),
       (:Product {sku: 'P003', name: '小米13', price: 3999})
2. 第一步:创建单属性索引(最常用)
cypher 复制代码
-- 为Person的name属性创建索引
CREATE INDEX person_name_index FOR (p:Person) ON (p.name)

-- 为Person的age属性创建索引  
CREATE INDEX person_age_index FOR (p:Person) ON (p.age)

-- 为Product的sku创建索引
CREATE INDEX product_sku_index FOR (p:Product) ON (p.sku)

-- 查看创建进度
CALL db.awaitIndexes()  -- 等待索引创建完成
3. 第二步:创建复合索引(多个属性)
cypher 复制代码
-- 当经常同时按city和age查询时
CREATE INDEX person_city_age_index FOR (p:Person) ON (p.city, p.age)

-- 复合索引适用于这样的查询:
MATCH (p:Person) 
WHERE p.city = '北京' AND p.age > 30  -- 两个条件都用上索引
RETURN p

-- 但不适用于:
MATCH (p:Person) 
WHERE p.city = '北京'  -- 只有city能用索引
RETURN p

MATCH (p:Person)
WHERE p.age > 30  -- 只有age不能用这个复合索引!
RETURN p
4. 第三步:创建文本索引(字符串搜索)
cypher 复制代码
-- 创建文本索引(Neo4j 5.x+)
CREATE TEXT INDEX product_name_text_index FOR (p:Product) ON (p.name)

-- 支持前缀匹配查询(比普通索引快)
MATCH (p:Product)
WHERE p.name STARTS WITH 'iPh'  -- 查找以'iPh'开头的
RETURN p

-- 普通索引不支持STARTS WITH,但文本索引支持!
5. 第四步:创建全文索引(模糊搜索)
cypher 复制代码
-- 全文索引可以跨多个标签和属性
CREATE FULLTEXT INDEX product_titles_and_descriptions
FOR (n:Product|Book)  -- 可以多个标签
ON EACH [n.name, n.description, n.title]  -- 可以多个属性

-- 使用全文搜索
CALL db.index.fulltext.queryNodes(
  'product_titles_and_descriptions', 
  '苹果手机'
) YIELD node, score
RETURN node.name, node.price, score
ORDER BY score DESC

-- 支持模糊匹配:'appel'也能找到'apple'

四、索引的最佳实践

1. 什么时候应该创建索引?
cypher 复制代码
-- ✅ 情况1:经常用于WHERE条件的属性
-- 如果经常这样查:
MATCH (u:User) WHERE u.email = 'xxx@yyy.com'  -- email应该建索引

-- ✅ 情况2:经常用于JOIN的属性
MATCH (u:User)-[:OWNS]->(o:Order)
WHERE u.user_id = '123'  -- user_id应该建索引

-- ✅ 情况3:唯一性约束会自动创建索引
CREATE CONSTRAINT FOR (u:User) REQUIRE u.user_id IS UNIQUE
-- 自动为user_id创建索引!

-- ❌ 情况4:很少查询的属性不要建索引
-- MATCH (p:Person) WHERE p.hobby = '游泳'  -- 如果不经常查,别建索引

-- ❌ 情况5:值种类太少的属性(如性别:男/女)
-- 建索引反而可能更慢
2. 索引的代价
cypher 复制代码
-- 索引不是免费的!
-- 1. 占用磁盘空间
-- 2. 降低写入速度(每次增删改都要更新索引)
-- 3. 增加内存使用

-- 查看索引大小
CALL db.indexes() YIELD name, type, labelsOrTypes, properties, totalSize
RETURN name, type, labelsOrTypes, properties, totalSize
3. 索引命名规范
cypher 复制代码
-- 好名字:一看就懂
CREATE INDEX idx_person_name FOR (p:Person) ON (p.name)
CREATE INDEX idx_user_email_for_login FOR (u:User) ON (u.email)
CREATE INDEX idx_product_sku_unique FOR (p:Product) ON (p.sku)

-- 按模式命名
CREATE INDEX idx_标签_属性_用途 FOR (n:Label) ON (n.property)

五、如何查看和管理索引

1. 查看所有索引
cypher 复制代码
-- 查看已创建的索引
CALL db.indexes()

-- 查看更详细信息
SHOW INDEXES

-- 查看特定标签的索引
SHOW INDEXES FOR (n:Person)

-- 查看索引使用统计
CALL db.index.usageStats()  -- 哪些索引被实际使用了
2. 测试索引效果
cypher 复制代码
-- 在查询前加EXPLAIN查看执行计划
EXPLAIN
MATCH (p:Person) WHERE p.name = '张三'
RETURN p

-- 结果会显示是否使用了索引
-- 如果看到"NodeIndexSeek",说明用了索引
-- 如果看到"NodeByLabelScan",说明没索引,全表扫描

-- 用PROFILE查看实际执行情况
PROFILE
MATCH (p:Person) WHERE p.name = '张三'
RETURN p
3. 删除不需要的索引
cypher 复制代码
-- 删除索引
DROP INDEX person_name_index

-- 安全删除(如果存在才删除)
DROP INDEX person_name_index IF EXISTS

-- 删除约束时,关联的索引也会自动删除
DROP CONSTRAINT constraint_name

六、实战案例:电商系统索引设计

cypher 复制代码
-- 电商系统推荐索引配置

-- 1. 用户表:登录和主键索引
CREATE CONSTRAINT user_id_unique FOR (u:User) REQUIRE u.user_id IS UNIQUE
CREATE INDEX user_email_index FOR (u:User) ON (u.email)        -- 登录用
CREATE INDEX user_phone_index FOR (u:User) ON (u.phone)        -- 登录用
CREATE INDEX user_created_at_index FOR (u:User) ON (u.created_at) -- 按时间查询

-- 2. 商品表:搜索和分类索引
CREATE CONSTRAINT product_id_unique FOR (p:Product) REQUIRE p.product_id IS UNIQUE
CREATE TEXT INDEX product_name_index FOR (p:Product) ON (p.name)  -- 名称搜索
CREATE INDEX product_category_index FOR (p:Product) ON (p.category_id)
CREATE INDEX product_price_index FOR (p:Product) ON (p.price)     -- 价格范围查询
CREATE INDEX product_status_index FOR (p:Product) ON (p.status)   -- 上架/下架

-- 3. 订单表:用户和时间索引
CREATE CONSTRAINT order_no_unique FOR (o:Order) REQUIRE o.order_no IS UNIQUE
CREATE INDEX order_user_id_index FOR (o:Order) ON (o.user_id)     -- 查用户订单
CREATE INDEX order_status_index FOR (o:Order) ON (o.status)       -- 按状态查询
CREATE INDEX order_created_at_index FOR (o:Order) ON (o.created_at) -- 时间范围

-- 4. 全文索引:商品搜索
CREATE FULLTEXT INDEX product_search_index 
FOR (p:Product) 
ON EACH [p.name, p.description, p.brand, p.tags]

-- 使用全文索引搜索
CALL db.index.fulltext.queryNodes('product_search_index', '苹果 手机 256GB')
YIELD node, score
WHERE node.price < 8000 AND node.stock > 0
RETURN node.name, node.price, score
ORDER BY score DESC
LIMIT 20

七、常见问题解答

Q1:索引创建后立即生效吗?
cypher 复制代码
-- 索引创建是异步的,需要等待
CREATE INDEX idx_name FOR (p:Person) ON (p.name)

-- 等待索引创建完成
CALL db.awaitIndexes()

-- 或者查看状态
CALL db.indexes() YIELD name, state
WHERE name = 'idx_name'
RETURN name, state  -- 状态应为'ONLINE'
Q2:如何知道应该给哪些属性建索引?
cypher 复制代码
-- 方法1:分析查询日志
CALL dbms.queryJit()  -- 查看慢查询

-- 方法2:使用性能监控
CALL db.stats.retrieve('QUERIES')  -- 查询统计

-- 方法3:经验法则:
-- 1. WHERE条件中经常出现的属性
-- 2. JOIN操作中使用的属性  
-- 3. ORDER BY中使用的属性
-- 4. 返回大量数据的过滤条件
Q3:索引会影响写入性能吗?
cypher 复制代码
-- 会的!每次增删改都要更新索引
-- 写入速度:无索引 > 有少量索引 > 有很多索引

-- 解决方法:
-- 1. 批量写入时,可以先删除索引,写入完再重建
DROP INDEX idx_name

-- 批量导入数据
LOAD CSV FROM 'file:///data.csv' AS row
CREATE (:Person {name: row[0], age: toInteger(row[1])})

-- 重建索引
CREATE INDEX idx_name FOR (p:Person) ON (p.name)
Q4:可以为关系创建索引吗?
cypher 复制代码
-- 可以直接为关系属性创建索引(Neo4j 4.0+)
CREATE INDEX rel_created_at_index FOR ()-[r:FOLLOWS]-() ON (r.created_at)

-- 查询时使用
MATCH ()-[r:FOLLOWS]->()
WHERE r.created_at > date('2023-01-01')
RETURN count(r)

八、索引检查清单

cypher 复制代码
-- 创建索引前问自己:
-- 1. 这个属性经常出现在WHERE条件中吗? ✅
-- 2. 这个查询执行慢吗?(用PROFILE检查) ✅  
-- 3. 数据量大吗?(小数据不需要索引) ✅
-- 4. 属性值的多样性高吗?(男/女这种不要建) ✅
-- 5. 写入频率高吗?(高写入要谨慎) ✅

-- 创建索引后:
-- 1. 等待索引构建完成:CALL db.awaitIndexes()
-- 2. 测试查询速度:对比前后的PROFILE结果
-- 3. 监控索引使用:CALL db.index.usageStats()
-- 4. 定期清理无用索引

九、快速参考命令

cypher 复制代码
-- 1. 创建索引
CREATE INDEX 索引名 FOR (n:标签) ON (n.属性)
CREATE INDEX 索引名 FOR (n:标签) ON (n.属性1, n.属性2)  -- 复合索引

-- 2. 查看索引
SHOW INDEXES
CALL db.indexes()

-- 3. 删除索引
DROP INDEX 索引名
DROP INDEX 索引名 IF EXISTS

-- 4. 检查索引使用
EXPLAIN MATCH ...  -- 查看执行计划
PROFILE MATCH ...   -- 查看性能

-- 5. 等待索引
CALL db.awaitIndexes()

记住:索引就像书的目录,没有目录找内容慢,但目录本身也占空间,而且书更新了目录也要更新!📚

Neo4j 核心概念全总结 🎯

一、最核心的 3 个概念(必须记住!)

复制代码
Neo4j 图数据库 = 节点 + 关系 + 属性
1. 节点(Node) - 图的"点"
  • 是什么:实体、对象、事物
  • 比如:人、商品、地点、事件
  • 可以有:标签(分类)、属性(信息)
2. 关系(Relationship) - 图的"边"
  • 是什么:连接两个节点的线
  • 特点:必须有方向、必须有类型、可以有属性
  • 比如:认识、购买、位于、属于
3. 属性(Property) - 节点和关系的"详细信息"
  • 是什么:键值对信息
  • 存储位置:节点和关系都可以有属性
  • 比如:姓名、年龄、时间、金额

二、5 大关键特性

1. 标签(Labels) - 节点的分类
cypher 复制代码
-- 就像给节点贴标签
CREATE (:Person)      -- "人"标签
CREATE (:Product)     -- "产品"标签  
CREATE (:Person:VIP)  -- 可以有多个标签
  • 作用:快速分类和查询
  • 一个节点可以有多个标签
2. 关系类型(Relationship Type) - 关系的分类
cypher 复制代码
CREATE ()-[:KNOWS]->()      -- "认识"关系
CREATE ()-[:BOUGHT]->()     -- "购买"关系
CREATE ()-[:LIVES_IN]->()   -- "居住"关系
  • 每个关系必须有一个类型
  • 类型名通常用大写(约定)
3. 图遍历(Traversal) - 沿着关系查找
cypher 复制代码
-- 找到朋友的朋友
MATCH (我)-[:FRIEND]->(朋友)-[:FRIEND]->(朋友的朋友)
RETURN 朋友的朋友

-- 多层关系查询
MATCH (我)-[:FRIEND*1..3]->(陌生人)
  • 可以沿着关系"走"到其他节点
  • 支持深度查询
4. 无固定模式(Schema-less)
cypher 复制代码
-- 不需要预先定义结构!
CREATE (:Person {name: '张三'})           -- 只有名字
CREATE (:Person {age: 25, city: '北京'})  -- 不同属性
CREATE (:Person {height: 180})           -- 新增属性
  • 随时添加新属性
  • 同一标签的节点可以有不同属性
5. Cypher 查询语言 - 图的 SQL
cypher 复制代码
-- 像说英语一样查询
MATCH (p:Person)-[:LIVES_IN]->(c:City)
WHERE p.age > 25
RETURN p.name, c.name
  • 专门为图设计的查询语言
  • 直观易读

三、与关系数据库对比

概念 关系数据库 (MySQL) Neo4j 比喻
数据结构 表 (Table) 图 (Graph) 表格 vs 网络
数据单元 行 (Row) 节点 (Node) 一行数据 vs 一个点
连接方式 外键 (Foreign Key) 关系 (Relationship) 数字引用 vs 直接连线
查询重点 JOIN 操作 关系遍历 查表连接 vs 沿着线走
灵活度 固定表结构 动态属性 严格表格 vs 灵活标签

四、核心优势(为什么用 Neo4j?)

1. 关系查询极快
cypher 复制代码
-- 传统SQL:需要多次JOIN
SELECT * FROM users u
JOIN friends f1 ON u.id = f1.user_id
JOIN friends f2 ON f1.friend_id = f2.user_id
-- 表越大越慢!

-- Neo4j:直接沿着关系走
MATCH (u:User)-[:FRIEND]->(f1)-[:FRIEND]->(f2)
RETURN f2
-- 速度几乎不受数据量影响
2. 最接近现实世界
复制代码
现实世界:
张三 --认识--> 李四 --同事--> 王五
  |                       |
 购买                    居住
  ↓                       ↓  
 iPhone                 北京

Neo4j完美映射:
(:Person {name:'张三'})-[:KNOWS]->(:Person {name:'李四'})
                                             |
                                           等等...
3. 适合的场景
  • 社交网络:朋友关系、关注关系
  • 推荐系统:买了A的人也买了B
  • 知识图谱:概念之间的关系
  • 欺诈检测:异常关系网络
  • 供应链:产品流转路径
  • 不适合:大量数值计算、简单CRUD

五、数据模型三层次

第1层:物理存储层
  • 节点存储文件
  • 关系存储文件
  • 属性存储文件
  • 用户看不见,但影响性能
第2层:逻辑模型层(你操作的部分)
复制代码
节点 --关系--> 节点
  ↓             ↓
属性           属性
第3层:业务模型层(你的应用)
复制代码
用户 --购买--> 商品
  ↓             ↓
地址           类别

六、必须掌握的 7 个 Cypher 操作

1. CREATE - 创建
cypher 复制代码
CREATE (:Person {name: '张三', age: 25})
CREATE (a)-[:KNOWS {since: 2020}]->(b)
2. MATCH - 查找
cypher 复制代码
MATCH (p:Person) RETURN p
MATCH (p:Person {name: '张三'}) RETURN p.age
3. WHERE - 过滤
cypher 复制代码
MATCH (p:Person) WHERE p.age > 20 RETURN p
4. SET - 修改/添加属性
cypher 复制代码
MATCH (p:Person {name: '张三'}) SET p.city = '北京'
5. DELETE - 删除
cypher 复制代码
MATCH (p:Person {name: '张三'}) DELETE p
-- 注意:有关系的节点要先删关系!
6. REMOVE - 删除属性/标签
cypher 复制代码
MATCH (p:Person {name: '张三'}) REMOVE p.age
7. RETURN - 返回结果
cypher 复制代码
MATCH (p:Person) RETURN p.name, p.age ORDER BY p.age DESC

七、高级概念摘要

1. 索引和约束
cypher 复制代码
-- 加速查询
CREATE INDEX FOR (p:Person) ON (p.name)

-- 保证数据唯一性
CREATE CONSTRAINT FOR (p:Person) REQUIRE p.id IS UNIQUE
2. 路径(Path)
cypher 复制代码
-- 节点和关系的序列
MATCH path = (a)-[:KNOWS*]->(b)
RETURN path, length(path)
3. 模式(Pattern)
cypher 复制代码
-- 描述图的结构
(a:Person)-[:WORKS_FOR]->(c:Company)<-[:WORKS_FOR]-(b:Person)
4. 变量(Variable)
cypher 复制代码
-- 给节点、关系、路径起别名
MATCH (p:Person)  -- p 是变量
WHERE p.age > 30
RETURN p

八、一句话记住 Neo4j

"用节点表示事物,用关系表示联系,两者都可以有详细信息,用 Cypher 语言像画画一样查询数据。"

九、学习路径建议

复制代码
第1步:理解节点+关系+属性(✓ 已掌握)
第2步:学会 CREATE、MATCH、RETURN
第3步:掌握 WHERE、SET、DELETE  
第4步:学习关系遍历和路径查询
第5步:了解索引和约束
第6步:实战项目练习

十、快速参考卡片

做什么 Cypher 命令 例子
创建节点 CREATE (n:Label {prop:value}) CREATE (:Person {name:'张三'})
查找节点 MATCH (n:Label) RETURN n MATCH (p:Person) RETURN p
条件查找 MATCH (n:Label) WHERE ... MATCH (p:Person) WHERE p.age>20
创建关系 CREATE (a)-[:TYPE]->(b) CREATE (a)-[:KNOWS]->(b)
查找关系 MATCH (a)-[r:TYPE]->(b) MATCH ()-[r:KNOWS]->()
修改属性 MATCH (n) SET n.prop=value SET p.age=30
删除节点 MATCH (n) DELETE n DELETE p
删除关系 MATCH ()-[r]->() DELETE r DELETE r
相关推荐
laplace01231 天前
向量库 Qdrant + 图数据库Neo4j+Embedding阿里百炼text-embedding-v3
数据库·embedding·agent·neo4j
小桥流水---人工智能1 天前
Neo4j:从文件里读数据(LOAD + FROM) → 在图里找节点(MATCH)或创建节点(MERGE) → 建立关系
neo4j
茅坑的小石头6 天前
Neo4j 超级简单关系图创建示例
neo4j
清水白石00810 天前
深入 Python 的底层世界:从 C 扩展到 ctypes 与 Cython 的本质差异全解析
c语言·python·neo4j
TGITCIC11 天前
讲透知识图谱Neo4j在构建Agent时到底怎么用(二)
人工智能·知识图谱·neo4j·ai agent·ai智能体·大模型落地·graphrag
TGITCIC12 天前
讲透知识图谱Neo4j在构建Agent时到底怎么用(一)
知识图谱·neo4j·ai agent·智能体·图搜索·ai智能体·graphrag
菜鸟冲锋号12 天前
从零搭建高可用GraphRAG系统:LangChain+Neo4j+FAISS+Qwen-7B实战指南
langchain·neo4j·faiss
一车小面包15 天前
Neo4j中的APOC
算法·neo4j
人工小情绪16 天前
python报错:AttributeError: module ‘numpy‘ has no attribute ‘object‘.
python·numpy·neo4j