MATCH

MATCH 子句使您能够定义数据库将在其图结构中搜索的特定模式。MATCH 子句可以指定模式中的节点、关系和属性,从而支持遍历图以检索相关数据的查询。

示例图

以下图表用于下方的示例

要重新创建该图,请在空的 Neo4j 数据库中运行以下查询

CREATE (charlie:Person:Actor {name: 'Charlie Sheen'}),
       (martin:Person:Actor {name: 'Martin Sheen'}),
       (michael:Person:Actor {name: 'Michael Douglas'}),
       (oliver:Person:Director {name: 'Oliver Stone'}),
       (rob:Person:Director {name: 'Rob Reiner'}),
       (wallStreet:Movie {title: 'Wall Street'}),
       (charlie)-[:ACTED_IN {role: 'Bud Fox'}]->(wallStreet),
       (martin)-[:ACTED_IN {role: 'Carl Fox'}]->(wallStreet),
       (michael)-[:ACTED_IN {role: 'Gordon Gekko'}]->(wallStreet),
       (oliver)-[:DIRECTED]->(wallStreet),
       (thePresident:Movie {title: 'The American President'}),
       (martin)-[:ACTED_IN {role: 'A.J. MacInerney'}]->(thePresident),
       (michael)-[:ACTED_IN {role: 'President Andrew Shepherd'}]->(thePresident),
       (rob)-[:DIRECTED]->(thePresident)

查找节点

MATCH 子句允许您指定不同复杂程度的节点模式以从图中检索数据。有关查找节点模式的更多信息,请参阅 模式 → 节点模式

查找所有节点

通过指定一个不带标签的单个节点模式,将返回图中的所有节点。

查找图中的所有节点
MATCH (n)
RETURN n
结果
n

(:Person {"name":"Charlie Sheen"})

(:Person {"name":"Martin Sheen"})

(:Person {"name":"Michael Douglas"})

(:Person {"name":"Oliver Stone"})

(:Person {"name":"Rob Reiner"})

(:Movie {"title":"Wall Street"})

(:Movie {"title":"The American President"})

行:7

查找带有特定标签的节点

查找所有带有 Movie 标签的节点
MATCH (movie:Movie)
RETURN movie.title
结果
movie.title

"Wall Street"

"The American President"

行:2

使用节点标签表达式的 MATCH

使用 OR (|) 标签表达式的节点模式
MATCH (n:Movie|Person)
RETURN n.name AS name, n.title AS title
结果
名称 (name) 标题

"Charlie Sheen"

<null>

"Martin Sheen"

<null>

"Michael Douglas"

<null>

"Oliver Stone"

<null>

"Rob Reiner"

<null>

<null>

"Wall Street"

<null>

"The American President"

行:7

使用否定 (!) 标签表达式的节点模式
MATCH (n:!Movie)
RETURN labels(n) AS label, count(n) AS labelCount
上述查询使用了 labels()count() 函数。
结果
标签 (label) labelCount

["Person", "Actor"]

3

["Person", "Director"]

2

行:2

有关 Cypher® 支持的所有标签表达式列表,请参阅 模式 → 标签表达式

查找关系

MATCH 子句允许您指定不同复杂程度的关系模式以从图中检索数据。与节点模式不同,关系模式在没有两端节点模式的情况下不能用于 MATCH 子句。有关关系模式的更多信息,请参阅 模式 → 关系模式

Cypher 的默认匹配模式 DIFFERENT RELATIONSHIPS 将在单个模式内仅匹配一次关系。但 REPEATABLE ELEMENTS 匹配模式则并非如此。更多信息,请参阅 匹配模式

空关系模式

通过应用 --,模式将匹配任何方向且不对关系类型或属性进行过滤的关系。

使用空关系模式查找连接的节点
MATCH (:Person {name: 'Oliver Stone'})--(n)
RETURN n AS connectedNodes
结果
connectedNodes

(:Movie {title: "Wall Street"})

行:1

有向关系模式

模式中关系的方向由箭头指示:--><--

查找所有通过出站关系连接到 Oliver Stone 的节点。
MATCH (:Person {name: 'Oliver Stone'})-->(movie:Movie)
RETURN movie.title AS movieTitle
结果
movieTitle

"Wall Street"

行:1

关系变量

可以为模式引入变量,用于过滤关系属性或返回关系。

查找别名关系的类型
MATCH (:Person {name: 'Oliver Stone'})-[r]->()
RETURN type(r) AS relType
上述查询使用了 type() 函数
结果
relType

"DIRECTED"

行:1

在无向关系上进行 MATCH

当模式包含已绑定的关系,且该关系模式未指定方向时,Cypher 将在两个方向上匹配该关系。

不带方向的关系模式
MATCH (a)-[:ACTED_IN {role: 'Bud Fox'}]-(b)
RETURN a, b
结果
a b

(:Movie {"title":"Wall Street"})

(:Person {"name":"Charlie Sheen"})

(:Person {"name":"Charlie Sheen"})

(:Movie {"title":"Wall Street"})

行:2

对关系类型进行过滤

可以通过在关系类型前使用冒号 (:) 在关系模式中指定关系类型。

ACTED_IN 关系类型上进行过滤的关系模式
MATCH (:Movie {title: 'Wall Street'})<-[:ACTED_IN]-(actor:Person)
RETURN actor.name AS actor
结果
actor

"Michael Douglas"

"Martin Sheen"

"Charlie Sheen"

行:3

使用关系类型表达式的 MATCH

可以使用 OR 符号 | 匹配包含多个关系类型之一的模式。

包含 ACTED_INDIRECTED 关系类型的关系模式
MATCH (:Movie {title: 'Wall Street'})<-[:ACTED_IN|DIRECTED]-(person:Person)
RETURN person.name AS person
结果
person

"Oliver Stone"

"Michael Douglas"

"Martin Sheen"

"Charlie Sheen"

行:4

由于关系每个只能有且仅有一个类型,()-[:A&B]→() 永远不会匹配到任何关系。

有关 Cypher 支持的所有关系类型表达式列表,请参阅 模式 → 标签表达式

查找多个关系

图模式可以包含多个关系模式。

包含多个关系模式的图模式
MATCH (:Person {name: 'Charlie Sheen'})-[:ACTED_IN]->(movie:Movie)<-[:DIRECTED]-(director:Person)
RETURN movie.title AS movieTitle, director.name AS director
结果
movieTitle director

"Wall Street"

"Oliver Stone"

行:1

带 WHERE 谓词的 MATCH

MATCH 子句常与 WHERE 子句搭配使用,后者添加谓词以细化模式,使其更具针对性。这些谓词是模式本身的一部分,而不仅仅是匹配后应用的过滤器。因此,请始终将 WHERE 子句与其对应的 MATCH 子句放在一起。

简单的 WHERE 谓词
MATCH (charlie:Person)-[:ACTED_IN]->(movie:Movie)
WHERE charlie.name = 'Charlie Sheen'
RETURN movie.title AS movieTitle
结果
movieTitle

"Wall Street"

行:1

更复杂的 WHERE 谓词
MATCH (martin:Person)-[:ACTED_IN]->(movie:Movie)
WHERE martin.name = 'Martin Sheen' AND NOT EXISTS {
    MATCH (movie)<-[:DIRECTED]-(director:Person {name: 'Oliver Stone'})
}
RETURN movie.title AS movieTitle
上述查询使用了 EXISTS 子查询
结果
movieTitle

"The American President"

行:1

更多信息,请参阅 WHERE 页面。

带参数的 MATCH

MATCH 子句可以与参数一起使用。

参数
{
  "movieTitle": "Wall Street",
  "actorRole": "Fox"
}
使用参数查找节点
MATCH (:Movie {title: $movieTitle})<-[r:ACTED_IN]-(p:Person)
WHERE r.role CONTAINS $actorRole
RETURN p.name AS actor, r.role AS role
上述查询使用了 CONTAINS 操作符
结果
actor role(角色)

"Charlie Sheen"

"Bud Fox"

"Martin Sheen"

"Carl Fox"

行:2

有关如何设置参数的更多信息,请参阅 语法 → 参数

查找路径

MATCH 子句也可用于将整个路径绑定到变量。

查找匹配模式的所有路径
MATCH path = ()-[:ACTED_IN]->(movie:Movie)
RETURN path
结果
path

(:Person {name: "Charlie Sheen"})-[:ACTED_IN {role: "Bud Fox"}]→(:Movie {title: "Wall Street"})

(:Person {name: "Martin Sheen"})-[:ACTED_IN {role: "Carl Fox"}]→(:Movie {title: "Wall Street"})

(:Person {name: "Martin Sheen"})-[:ACTED_IN {role: "A.J. MacInerney"}]→(:Movie {title: "The American President"})

(:Person {name: "Michael Douglas"})-[:ACTED_IN {role: "Gordon Gekko"}]→(:Movie {title: "Wall Street"})

(:Person {name: "Michael Douglas"})-[:ACTED_IN {role: "President Andrew Shepherd"}]→(:Movie {title: "The American President"})

行:5

查找匹配包含 WHERE 谓词模式的路径
MATCH path = (:Person)-[:ACTED_IN]->(movie:Movie)<-[:DIRECTED]-(:Person)
WHERE movie.title = 'Wall Street'
RETURN path
结果
path

(:Person {name: "Charlie Sheen"})-[:ACTED_IN {role: "Bud Fox"}]→(:Movie {title: "Wall Street"})←[:DIRECTED]-(:Person {name: "Oliver Stone"})

(:Person {name: "Martin Sheen"})-[:ACTED_IN {role: "Carl Fox"}]→(:Movie {title: "Wall Street"})←[:DIRECTED]-(:Person {name: "Oliver Stone"})

(:Person {name: "Michael Douglas"})-[:ACTED_IN {role: "Gordon Gekko"}]→(:Movie {title: "Wall Street"})←[:DIRECTED]-(:Person {name: "Oliver Stone"})

行:3

有关 MATCH 如何用于查找不同复杂程度模式(包括 量化路径模式量化关系 以及节点间的 最短路径)的更多信息,请参阅 模式 一节。

多个 MATCH 子句、WITH 子句和子句组合

在 Cypher 中,查询的行为由其子句定义。每个子句接收当前的图状态和中间结果表,对其进行处理,并将更新后的图状态和结果传递给下一个子句。第一个子句从图的初始状态和空表开始,而最后一个子句生成查询结果。

链接连续的 MATCH 子句
MATCH (:Person {name: 'Martin Sheen'})-[:ACTED_IN]->(movie:Movie) (1)
MATCH (director:Person)-[:DIRECTED]->(movie) (2)
RETURN director.name AS director, movie.title AS movieTitle
1 第一个 MATCH 子句的结果是变量 movie,它保存了 Martin Sheen 曾经 ACTED_IN(出演)的所有 Movie
2 第二个 MATCH 子句使用 movie 变量来查找任何与 Martin Sheen 出演的 Movie 节点之间存在 DIRECTED(导演)关系的 Person 节点。
结果
director movieTitle

"Oliver Stone"

"Wall Street"

"Rob Reiner"

"The American President"

行:2

变量可以通过在另一个操作中被引用来隐式传递到下一个子句。变量也可以使用 WITH 子句显式传递给下一个子句。如果变量未被隐式或显式传递给后续子句,它将被丢弃,且在查询的后续部分中无法引用。

使用 WITH 和多个 MATCH 子句
MATCH (actors:Person)-[:ACTED_IN]->(movies:Movie) (1)
WITH actors, count(movies) AS movieCount (2)
ORDER BY movieCount DESC
LIMIT 1 (3)
MATCH (actors)-[:ACTED_IN]->(movies) (4)
RETURN actors.name AS actor, movieCount, collect(movies.title) AS movies
1 在此步骤中匹配到的 PersonMovie 节点被存储在变量中,随后传递给查询的下一行。
2 movies 变量通过其在 count() 函数中的出现而被隐式导入。WITH 子句显式导入了 actors 变量。
3 ORDER BY 子句按 movieCount 降序排列结果,确保出演电影数量最多的 Person 出现在顶部,而 LIMIT 1 确保所有其他 Person 节点被丢弃。
4 第二个 MATCH 子句查找与当前绑定到 actors 变量的 Person 节点相关联的所有 Movie 节点。
上述查询使用了 collect() 函数
结果
actor movieCount movies

"Martin Sheen"

2

["Wall Street", "The American President"]

行:1

有关 Cypher 查询工作原理的更多信息,请参阅 子句组合

使用动态节点标签和关系类型的 MATCH

在匹配节点和关系时,节点标签和关系类型可以在表达式、参数和变量中被动态引用。这允许更灵活的查询并降低 Cypher 注入风险。(有关 Cypher 注入的更多信息,请参阅 Neo4j 知识库 → 防止 Cypher 注入)。

动态匹配节点标签的语法
MATCH (n:$(<expr>))
MATCH (n:$any(<expr>))
MATCH (n:$all(<expr>))
MATCH (n:$all(<expr>)) 在功能上等同于 MATCH (n:$(<expr>))
动态匹配关系类型的语法
MATCH ()-[r:$(<expr>))]->()
MATCH ()-[r:$any(<expr>)]->()
MATCH ()-[r:$all(<expr>))]->()

表达式必须求值为 STRING NOT NULL | LIST<STRING NOT NULL> NOT NULL 值。如果您在具有动态关系类型的关系模式中使用包含多项的 LIST<STRING>,则不会返回任何结果。这是因为一个关系只能有且仅有一个类型。

动态匹配标签
WITH ["Person", "Director"] AS labels
MATCH (directors:$(labels))
RETURN directors
结果
directors

(:Person:Director {name: "Oliver Stone"})

(:Person:Director {name: "Rob Reiner"})

行:2

使用 any() 动态匹配节点
MATCH (n:$any(["Movie", "Actor"]))
RETURN n AS nodes
结果
节点

(:Person:Actor {name: "Charlie Sheen"})

(:Person:Actor {name: "Martin Sheen"})

(:Person:Actor {name: "Michael Douglas"})

(:Movie {title: "Wall Street"})

(:Movie {title: "The American President"})

行:5

参数
{
  "label": "Movie"
}
使用参数动态匹配节点
MATCH (movie:$($label))
RETURN movie.title AS movieTitle
结果
movieTitle

"Wall Street"

"The American President"

行:2

使用变量动态匹配关系
CALL db.relationshipTypes()
YIELD relationshipType
MATCH ()-[r:$(relationshipType)]->()
RETURN relationshipType, count(r) AS relationshipCount
结果
关系类型 (relationshipType) relationshipCount

"ACTED_IN"

5

"DIRECTED"

2

行:2

性能注意事项

使用动态值的 MATCH 查询性能可能不如使用静态值的查询。Neo4j 正在积极努力提高这些查询的性能。下表概述了特定 Neo4j 版本的性能注意事项。

Neo4j 版本与性能注意事项
Neo4j 版本 性能注意事项

5.26 — 2025.07

Cypher 规划器无法利用带有 索引扫描或查找索引,必须转而使用 AllNodesScan 操作符,该操作符会读取节点存储中的所有节点,因此代价更高。

2025.08 — 2025.10

当动态匹配节点标签和关系类型时,Cypher 规划器能够利用 令牌查找索引。这是通过引入三个新的查询规划操作符实现的:DynamicLabelNodeLookupDynamicDirectedRelationshipTypeLookupDynamicUndirectedRelationshipTypeLookup。但是,它无法在属性值上使用索引。例如,MATCH (n:$(Label) {foo: bar}) 不会使用 n.foo 上的任何索引,但可以在 $(label) 上使用 DynamicLabelNodeLookup

2025.11 — 当前

Cypher 规划器能够利用属性值上的索引,但是

  • 仅支持范围索引上的精确查找(不支持全文或空间索引)。

  • 无法利用索引顺序,因此如果查询后续需要,规划器必须插入单独的排序操作。

  • 并行运行时查找和扫描是单线程的。

  • 在为查询的动态部分生成结果时,规划器不会组合多个属性索引查找。例如,将 $any 与多个共享属性索引的标签结合使用,会导致操作符基于选择性选择其中一个索引,然后遍历查找结果并对表达式的其余部分进行过滤。 + 示例

    CREATE RANGE INDEX actor_has_birthyear FOR (a:Actor) ON (a.birthYear)
    CREATE RANGE INDEX director_has_birthyear FOR (d:Director) ON (d.birthYear)
    
    MATCH (p:$any(["Actor", "Director"]) { birthYear: 1983 }) RETURN p.name