变长路径 #
一、变长路径概述 #
1.1 什么是变长路径 #
变长路径允许匹配不确定长度的关系序列,是图数据库的核心特性之一。
text
固定长度:-[:KNOWS]-> 长度=1
变长路径:-[:KNOWS*1..3]-> 长度=1到3
无限长度:-[:KNOWS*]-> 长度=任意
1.2 变长路径语法 #
cypher
-[:TYPE*min..max]->
| 语法 | 说明 |
|---|---|
* |
任意长度 |
*n |
精确n跳 |
*n.. |
最少n跳 |
*..n |
最多n跳 |
*n..m |
n到m跳 |
二、基本语法 #
2.1 任意长度 #
cypher
MATCH (a)-[:KNOWS*]->(b)
RETURN a, b
2.2 精确长度 #
cypher
MATCH (a)-[:KNOWS*2]->(b)
RETURN a, b
2.3 最小长度 #
cypher
MATCH (a)-[:KNOWS*2..]->(b)
RETURN a, b
2.4 最大长度 #
cypher
MATCH (a)-[:KNOWS*..3]->(b)
RETURN a, b
2.5 范围长度 #
cypher
MATCH (a)-[:KNOWS*1..3]->(b)
RETURN a, b
三、变长关系 #
3.1 单一关系类型 #
cypher
MATCH (a)-[:KNOWS*1..3]->(b)
RETURN a.name, b.name
3.2 多种关系类型 #
cypher
MATCH (a)-[:KNOWS|FRIEND_OF*1..3]->(b)
RETURN a.name, b.name
3.3 任意关系类型 #
cypher
MATCH (a)-[*1..3]->(b)
RETURN a.name, b.name
3.4 带方向 #
cypher
MATCH (a)-[:KNOWS*1..3]->(b)
RETURN a, b
MATCH (a)<-[:KNOWS*1..3]-(b)
RETURN a, b
3.5 无方向 #
cypher
MATCH (a)-[:KNOWS*1..3]-(b)
RETURN a, b
四、关系变量 #
4.1 捕获关系列表 #
cypher
MATCH (a)-[r:KNOWS*1..3]->(b)
RETURN r
4.2 访问关系属性 #
cypher
MATCH (a)-[r:KNOWS*1..3]->(b)
RETURN [rel IN r | rel.since] AS years
4.3 关系类型列表 #
cypher
MATCH (a)-[r*1..3]->(b)
RETURN [rel IN r | type(rel)] AS rel_types
4.4 关系数量 #
cypher
MATCH (a)-[r:KNOWS*1..3]->(b)
RETURN size(r) AS rel_count
五、路径变量 #
5.1 捕获完整路径 #
cypher
MATCH p = (a)-[:KNOWS*1..3]->(b)
RETURN p
5.2 路径长度 #
cypher
MATCH p = (a)-[:KNOWS*1..3]->(b)
RETURN length(p) AS path_length
5.3 路径节点 #
cypher
MATCH p = (a)-[:KNOWS*1..3]->(b)
RETURN nodes(p) AS path_nodes
5.4 路径关系 #
cypher
MATCH p = (a)-[:KNOWS*1..3]->(b)
RETURN relationships(p) AS path_rels
六、过滤条件 #
6.1 按长度过滤 #
cypher
MATCH p = (a)-[:KNOWS*1..5]->(b)
WHERE length(p) >= 2
RETURN p
6.2 按节点属性过滤 #
cypher
MATCH p = (a)-[:KNOWS*1..5]->(b)
WHERE ALL(n IN nodes(p) WHERE n.status = 'active')
RETURN p
6.3 按关系属性过滤 #
cypher
MATCH p = (a)-[r:KNOWS*1..5]->(b)
WHERE ALL(rel IN r WHERE rel.since > 2020)
RETURN p
6.4 排除特定节点 #
cypher
MATCH p = (a)-[:KNOWS*1..5]->(b)
WHERE NONE(n IN nodes(p) WHERE n.name = 'Jerry')
RETURN p
6.5 包含特定节点 #
cypher
MATCH p = (a)-[:KNOWS*1..5]->(b)
WHERE ANY(n IN nodes(p) WHERE n.name = 'Jerry')
RETURN p
6.6 单次通过 #
cypher
MATCH p = (a)-[:KNOWS*1..5]->(b)
WHERE size(nodes(p)) = size(apoc.coll.toSet(nodes(p)))
RETURN p
七、实际应用场景 #
7.1 社交网络:朋友的朋友 #
cypher
MATCH (me:Person {name: 'Tom'})-[:KNOWS*2..2]->(fof:Person)
WHERE NOT (me)-[:KNOWS]->(fof)
RETURN fof.name, count(*) AS mutual_friends
ORDER BY mutual_friends DESC
LIMIT 10
7.2 社交网络:N度人脉 #
cypher
MATCH p = (me:Person {name: 'Tom'})-[:KNOWS*1..4]->(other:Person)
RETURN
length(p) AS degree,
count(DISTINCT other) AS people_count
ORDER BY degree
7.3 组织架构:层级查询 #
cypher
MATCH p = (manager:Employee)-[:MANAGES*1..5]->(employee:Employee)
WHERE manager.name = 'Tom'
RETURN
employee.name,
length(p) AS level,
[n IN nodes(p) | n.title] AS hierarchy
ORDER BY level
7.4 知识图谱:概念关联 #
cypher
MATCH p = (a:Concept)-[:RELATED_TO*1..3]->(b:Concept)
WHERE a.name = 'Graph Database'
RETURN
b.name,
length(p) AS distance,
[n IN nodes(p) | n.name] AS path
ORDER BY distance
LIMIT 20
7.5 交通网络:可达性 #
cypher
MATCH p = (a:City)-[:CONNECTED_TO*1..5]->(b:City)
WHERE a.name = 'New York'
RETURN
b.name,
length(p) AS stops,
[n IN nodes(p) | n.name] AS route
ORDER BY stops
LIMIT 10
八、性能优化 #
8.1 限制最大长度 #
cypher
MATCH (a)-[:KNOWS*1..3]->(b)
RETURN a, b
8.2 使用索引 #
cypher
CREATE INDEX FOR (p:Person) ON (p.name)
MATCH (a:Person {name: 'Tom'})-[:KNOWS*1..3]->(b)
RETURN b
8.3 使用WHERE过滤 #
cypher
MATCH (a)-[:KNOWS*1..5]->(b)
WHERE a.name = 'Tom' AND b.status = 'active'
RETURN b
8.4 使用LIMIT #
cypher
MATCH (a)-[:KNOWS*1..5]->(b)
RETURN a, b
LIMIT 100
8.5 避免无限长度 #
cypher
MATCH (a)-[:KNOWS*]->(b)
RETURN a, b
8.6 性能建议 #
text
建议:
├── 始终设置最大长度限制
├── 使用索引加速起始节点查找
├── 使用WHERE过滤减少结果
├── 使用LIMIT限制返回数量
└── 使用PROFILE分析查询
九、高级技巧 #
9.1 获取每层的节点 #
cypher
MATCH p = (a:Person {name: 'Tom'})-[:KNOWS*1..3]->(b:Person)
WITH length(p) AS degree, collect(DISTINCT b.name) AS people
RETURN degree, people
ORDER BY degree
9.2 计算路径权重 #
cypher
MATCH p = (a)-[r:KNOWS*1..3]->(b)
WITH p, reduce(total = 0, rel IN r | total + coalesce(rel.weight, 1)) AS total_weight
RETURN p, total_weight
ORDER BY total_weight
9.3 查找所有路径 #
cypher
MATCH p = (a:Person {name: 'Tom'})-[:KNOWS*1..3]->(b:Person {name: 'Jerry'})
RETURN
[n IN nodes(p) | n.name] AS path,
length(p) AS distance
ORDER BY distance
9.4 查找最短路径 #
cypher
MATCH p = (a:Person {name: 'Tom'})-[:KNOWS*1..5]->(b:Person {name: 'Jerry'})
WITH p
ORDER BY length(p)
LIMIT 1
RETURN p
十、常见问题 #
10.1 循环路径 #
cypher
MATCH p = (a)-[:KNOWS*1..5]->(a)
RETURN p
10.2 重复节点 #
cypher
MATCH p = (a)-[:KNOWS*1..5]->(b)
WHERE size(nodes(p)) > size(apoc.coll.toSet(nodes(p)))
RETURN p
10.3 性能问题 #
cypher
MATCH (a)-[:KNOWS*]->(b)
RETURN a, b
10.4 内存溢出 #
cypher
MATCH (a)-[:KNOWS*1..10]->(b)
RETURN a, b
十一、实际应用示例 #
11.1 推荐好友 #
cypher
MATCH (me:User {id: 'user_001'})-[:FRIEND_OF*2..2]->(recommended:User)
WHERE NOT (me)-[:FRIEND_OF]->(recommended)
WITH recommended, count(*) AS mutual_friends
ORDER BY mutual_friends DESC
LIMIT 10
RETURN recommended.name, mutual_friends
11.2 影响力分析 #
cypher
MATCH p = (influencer:User)-[:INFLUENCES*1..3]->(user:User)
WITH influencer, count(DISTINCT user) AS influence_count
ORDER BY influence_count DESC
LIMIT 10
RETURN influencer.name, influence_count
11.3 信息传播路径 #
cypher
MATCH p = (source:User)-[:SHARED*1..5]->(target:User)
WHERE source.id = 'user_001'
RETURN
target.name,
length(p) AS hops,
[n IN nodes(p) | n.name] AS propagation_path
ORDER BY hops
LIMIT 20
十二、总结 #
变长路径要点:
| 语法 | 说明 | 示例 |
|---|---|---|
* |
任意长度 | -[:KNOWS*]-> |
*n |
精确n跳 | -[:KNOWS*2]-> |
*n.. |
最少n跳 | -[:KNOWS*2..]-> |
*..n |
最多n跳 | -[:KNOWS*..3]-> |
*n..m |
n到m跳 | -[:KNOWS*1..3]-> |
最佳实践:
- 始终设置最大长度限制
- 使用索引加速起始节点查找
- 使用过滤条件减少结果
- 使用LIMIT限制返回数量
- 使用PROFILE分析性能
下一步,让我们学习最短路径!
最后更新:2026-03-27