入门
本节包含一个入门指南,涵盖了使用 Cypher® 查询进行图模式匹配的一些基本功能。
示例图
本教程中使用的示例图是一个火车站点 (Stations) 模型,以及在这些站点停靠的各种火车服务及其停靠点 (Stops)。
要重新创建该图,请在空的 Neo4j 数据库中运行以下查询
CREATE (n1:Station {name: 'Denmark Hill'}),
(n5:Station {name: 'Battersea Park'}),
(n6:Station {name: 'Wandsworth Road'}),
(n15:Station {name: 'Clapham High Street'}),
(n16:Station {name: 'Peckham Rye'}),
(n17:Station {name: 'Brixton'}),
(n14:Station {name: 'London Victoria'}),
(n18:Station {name: 'Clapham Junction'}),
(p10:Stop {departs: time('22:37'), arrives: time('22:36')}),
(p0:Stop {departs: time('22:41'), arrives: time('22:41')}),
(p2:Stop {departs: time('22:43'), arrives: time('22:43')}),
(p17:Stop {arrives: time('22:50'), departs: time('22:50')}),
(p18:Stop {arrives: time('22:46'), departs: time('22:46')}),
(p19:Stop {departs: time('22:33'), arrives: time('22:31')}),
(p21:Stop {arrives: time('22:55')}),
(p20:Stop {departs: time('22:44'), arrives: time('22:43')}),
(p22:Stop {arrives: time('22:55')}),
(p23:Stop {arrives: time('22:48')}),
(n15)-[:LINK {distance: 1.96}]->(n1)-[:LINK {distance: 0.86}]->(n16),
(n15)-[:LINK {distance: 0.39}]->(n6)<-[:LINK {distance: 0.7}]-(n5)-[:LINK {distance: 1.24}]->(n14), (n5)-[:LINK {distance: 1.45}]->(n18),
(n14)<-[:LINK {distance: 3.18}]-(n17)-[:LINK {distance: 1.11}]->(n1),
(p2)-[:CALLS_AT]->(n6), (p17)-[:CALLS_AT]->(n5), (p19)-[:CALLS_AT]->(n16),
(p22)-[:CALLS_AT]->(n14), (p18)-[:CALLS_AT]->(n18), (p0)-[:CALLS_AT]->(n15), (p23)-[:CALLS_AT]->(n5), (p20)-[:CALLS_AT]->(n1),
(p21)-[:CALLS_AT]->(n14), (p10)-[:CALLS_AT]->(n1), (p19)-[:NEXT]->(p10)-[:NEXT]->(p0)-[:NEXT]->(p2)-[:NEXT]->(p23),
(p22)<-[:NEXT]-(p17)<-[:NEXT]-(p18), (p21)<-[:NEXT]-(p20)
匹配固定长度路径
一对空括号是一个节点模式,它将匹配任何节点。以下示例获取图中所有节点的计数
MATCH ()
RETURN count(*) AS numNodes
| numNodes |
|---|
|
行:1 |
为节点模式添加标签将过滤出带有该标签的节点(请参阅标签表达式)。以下查询获取所有带有 Stop 标签的节点计数
MATCH (:Stop)
RETURN count(*) AS numStops
| numStops |
|---|
|
行:1 |
路径模式可以匹配关系及其连接的节点。以下查询获取所有在 Denmark Hill 停靠的列车的到达时间
MATCH (s:Stop)-[:CALLS_AT]->(:Station {name: 'Denmark Hill'})
RETURN s.arrives AS arrivalTime
| arrivalTime |
|---|
|
|
行:2 |
路径模式可以包含内联的 WHERE 子句。以下查询获取在 22:37 从 Denmark Hill 出发的服务的下一个停靠点
MATCH (n:Station {name: 'Denmark Hill'})<-[:CALLS_AT]-
(s:Stop WHERE s.departs = time('22:37'))-[:NEXT]->
(:Stop)-[:CALLS_AT]->(d:Station)
RETURN d.name AS nextCallingPoint
| nextCallingPoint |
|---|
|
行:1 |
更多信息,请参阅固定长度模式。
匹配可变长度路径
仅遍历指定类型关系的可变长度路径可以使用量化关系进行匹配。关系模式中声明的任何变量都将返回所遍历的关系列表。以下查询返回通过连接 Peckham Rye 和 Clapham Junction 站点的所有 LINK 所行进的总距离
MATCH (:Station {name: 'Peckham Rye'})-[link:LINK]-+
(:Station {name: 'Clapham Junction'})
RETURN reduce(acc = 0.0, l IN link | round(acc + l.distance, 2)) AS
totalDistance
| totalDistance |
|---|
|
|
行:2 |
|
|
可变长度路径也可以通过量化路径模式进行匹配,该模式允许使用 WHERE 子句并访问路径遍历的节点。以下查询返回从 Peckham Rye 到 London Victoria 路线上的停靠点列表,其中站点间的任何距离都不超过两英里
MATCH (:Station {name: 'Peckham Rye'})
(()-[link:LINK]-(s) WHERE link.distance <= 2)+
(:Station {name: 'London Victoria'})
UNWIND s AS station
RETURN station.name AS callingPoint
| callingPoint |
|---|
|
|
|
|
|
行:5 |
节点模式内部的 WHERE 子句本身可以包含路径模式。以下查询使用 EXISTS 子查询来锚定一系列 Stops 中的最后一个 Stop,并返回在 Denmark Hill 停靠的所有服务的出发时间、到达时间和最终目的地
MATCH (:Station {name: 'Denmark Hill'})<-[:CALLS_AT]-(s1:Stop)-[:NEXT]->+
(sN:Stop WHERE NOT EXISTS { (sN)-[:NEXT]->(:Stop) })-[:CALLS_AT]->
(d:Station)
RETURN s1.departs AS departure, sN.arrives AS arrival,
d.name AS finalDestination
| departure | arrival | finalDestination |
|---|---|---|
|
|
|
|
|
|
行:2 |
||
在量化路径模式中声明的节点变量会被绑定到节点列表,这些列表可以被展开并在随后的 MATCH 子句中使用。以下查询列出了 Peckham Rye 到 Battersea Park 火车服务的停靠点
MATCH (:Station {name: 'Peckham Rye'})<-[:CALLS_AT]-(:Stop)
(()-[:NEXT]->(s:Stop))+
()-[:CALLS_AT]->(:Station {name: 'Battersea Park'})
UNWIND s AS stop
MATCH (stop)-[:CALLS_AT]->(station:Station)
RETURN stop.arrives AS arrival, station.name AS callingPoint
| arrival | callingPoint |
|---|---|
|
|
|
|
|
|
|
|
行:4 |
|
在路径模式中重复使用节点变量可以使同一个节点在路径中被多次绑定(请参阅等连接 (equijoins))。以下查询查找由 Stations 之间的 LINK 形成的循环(即经过同一个 Station 一次以上)上的所有站点
MATCH (n:Station)-[:LINK]-+(n)
RETURN DISTINCT n.name AS station
| station |
|---|
|
|
|
|
|
|
行数: 6 |
可以使用图模式匹配复杂的非线性路径,这是一种通过重复节点变量(即等连接)连接的路径模式的逗号分隔列表。例如,一位乘客从 Denmark Hill 出发,想要搭乘在 22:46 从 Clapham Junction 出发前往 London Victoria 的火车服务。以下查询查找从 Denmark Hill 出发的时间,以及换乘的 Station 和到达时间
MATCH (:Station {name: 'Denmark Hill'})<-[:CALLS_AT]-
(s1:Stop)-[:NEXT]->+(s2:Stop)-[:CALLS_AT]->
(c:Station)<-[:CALLS_AT]-(x:Stop),
(:Station {name: 'Clapham Junction'})<-[:CALLS_AT]-
(t1:Stop)-[:NEXT]->+(x)-[:NEXT]->+(:Stop)-[:CALLS_AT]->
(:Station {name: 'London Victoria'})
WHERE t1.departs = time('22:46')
AND s2.arrives < x.departs
RETURN s1.departs AS departure, s2.arrives AS changeArrival,
c.name AS changeAt
| departure | changeArrival | changeAt |
|---|---|---|
|
|
|
行:1 |
||
更多信息,请参阅可变长度模式。
匹配最短路径
可以使用 SHORTEST 关键字找到两个节点之间的最短路径
MATCH p = SHORTEST 1
(:Station {name: "Brixton"})
(()-[:LINK]-(:Station))+
(:Station {name: "Clapham Junction"})
RETURN [station IN nodes(p) | station.name] AS route
| route |
|---|
|
行:1 |
若要查找所有最短路径,可以使用 ALL SHORTEST 关键字
MATCH p = ALL SHORTEST
(:Station {name: "Denmark Hill"})
(()-[:LINK]-(:Station))+
(:Station {name: "Clapham Junction"})
RETURN [station IN nodes(p) | station.name] AS route
| route |
|---|
|
|
行:2 |
通常,可以使用 SHORTEST k 返回 k 条最短路径。以下查询返回两条最短路径
MATCH p = SHORTEST 2
(:Station {name: "Denmark Hill"})
(()-[:LINK]-(:Station))+
(:Station {name: "Clapham High Street"})
RETURN [station IN nodes(p) | station.name] AS route
| route |
|---|
|
|
行:2 |
更多信息,请参阅最短路径。