变长路径 #

一、变长路径概述 #

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]->

最佳实践:

  1. 始终设置最大长度限制
  2. 使用索引加速起始节点查找
  3. 使用过滤条件减少结果
  4. 使用LIMIT限制返回数量
  5. 使用PROFILE分析性能

下一步,让我们学习最短路径!

最后更新:2026-03-27