可选匹配

介绍

OPTIONAL MATCHMATCH 一样,将模式与图数据库匹配。区别在于,如果没有找到匹配项,OPTIONAL MATCH 将对模式的缺失部分使用 null。因此,OPTIONAL MATCH 可以被认为是 Cypher® 中的 SQL 外连接等效项。

使用 OPTIONAL MATCH 时,要么整个模式匹配,要么不匹配。WHERE 子句是模式描述的一部分,其谓词将在查找匹配项时被考虑,而不是之后。这在多个 (OPTIONAL) MATCH 子句的情况下尤其重要,因为将 WHERE 与其所属的 MATCH 放在一起至关重要。

要了解 OPTIONAL MATCH 子句中使用的模式,请阅读 模式.

示例图

以下图用于下面的示例

graph optional match clause

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

CREATE
  (charlie:Person {name: 'Charlie Sheen'}),
  (martin:Person {name: 'Martin Sheen'}),
  (michael:Person {name: 'Michael Douglas'}),
  (oliver:Person {name: 'Oliver Stone'}),
  (rob:Person {name: 'Rob Reiner'}),
  (wallStreet:Movie {title: 'Wall Street'}),
  (charlie)-[:ACTED_IN]->(wallStreet),
  (martin)-[:ACTED_IN]->(wallStreet),
  (michael)-[:ACTED_IN]->(wallStreet),
  (oliver)-[:DIRECTED]->(wallStreet),
  (thePresident:Movie {title: 'The American President'}),
  (martin)-[:ACTED_IN]->(thePresident),
  (michael)-[:ACTED_IN]->(thePresident),
  (rob)-[:DIRECTED]->(thePresident),
  (martin)-[:FATHER_OF]->(charlie)

更详细的 OPTIONAL MATCH

与 SQL 一样,Cypher 查询使用各种子句构建,这些子句链接在一起,在每个子句之间传递中间结果。例如,来自一个 MATCH 子句的匹配变量将提供下一个子句存在的上下文。但是,Neo4j 和 SQL 之间存在两个重要区别,这有助于进一步解释 OPTIONAL MATCH

  1. 虽然使用索引和约束来强制执行部分模式是可能的也是建议的,但 Neo4j 提供比关系数据库更高的模式灵活性。Neo4j 数据库中的节点和关系不需要具有特定的属性集,因为同一图中的其他节点或关系具有该属性(除非在特定属性上创建了 属性存在约束)。

  2. Cypher 中的查询作为管道运行。如果一个子句没有返回任何结果,它实际上将结束查询,因为后续子句将没有数据可供执行。

例如,以下查询没有返回任何结果

MATCH (a:Person {name: 'Martin Sheen'})
MATCH (a)-[r:DIRECTED]->()
RETURN a.name, r
(no changes, no records)

这是因为第二个 MATCH 子句没有返回任何数据(图中没有连接到 Martin SheenDIRECTED 关系),因此无法传递到 RETURN 子句。

但是,将第二个 MATCH 子句替换为 OPTIONAL MATCH 会返回结果。这是因为,与 MATCH 不同,OPTIONAL MATCH 允许在子句之间传递 null 值。

MATCH (p:Person {name: 'Martin Sheen'})
OPTIONAL MATCH (p)-[r:DIRECTED]->()
RETURN p.name, r
表 1. 结果
p.name r

"Martin Sheen"

<null>

行数:1

因此,OPTIONAL MATCH 可用于检查图中是否存在缺失值和现有值,并将没有任何数据的行传递给查询中的后续子句。

可选关系

如果关系的存在是可选的,请使用 OPTIONAL MATCH 子句。如果关系存在,则返回该关系。如果不存在,则返回 null

MATCH (a:Movie {title: 'Wall Street'})
OPTIONAL MATCH (a)-->(x)
RETURN x

返回 null,因为 Movie 节点 Wall Street 没有传出关系。

表 2. 结果
x

<null>

行数:1

另一方面,以下查询不会返回 null,因为 Person 节点 Charlie Sheen 具有一个传出关系。

MATCH (a:Person {name: 'Charlie Sheen'})
OPTIONAL MATCH (a)-->(x)
RETURN x
表 3. 结果
x

{"title":"Wall Street"}

行数:2

可选元素上的属性

如果属性的存在是可选的,请使用 OPTIONAL MATCH 子句。如果指定的属性不存在,则返回 null

MATCH (a:Movie {title: 'Wall Street'})
OPTIONAL MATCH (a)-->(x)
RETURN x, x.name

返回元素 x(此查询中的 null),以及其 name 属性的 null,因为 Movie 节点 Wall Street 没有传出关系。

表 4. 结果
x x.name

<null>

<null>

行数:1

以下查询仅对缺少 name 属性的节点返回 null

MATCH (a:Person {name: 'Martin Sheen'})
OPTIONAL MATCH (a)-->(x)
RETURN x, x.name
表 5. 结果
x x.name

{"title":"Wall Street"}

<null>

{"name":"Charlie Sheen"}

"Charlie Sheen"

{"title":"The American President"}

<null>

行数:3

可选类型和命名关系

使用 OPTIONAL MATCH 时,也可以查找特定关系类型

MATCH (a:Movie {title: 'Wall Street'})
OPTIONAL MATCH (a)-[r:ACTED_IN]->()
RETURN a.title, r

这将返回 Movie 节点 Wall Street 的标题,并且由于该节点没有传出 ACTED_IN 关系,因此对于变量 r 表示的关系返回 null

表 6. 结果
a.title r

"Wall Street"

<null>

行数:1

但是,以下查询不会返回 null,因为它正在查找 Movie 节点 Wall Street 的传入 ACTED_IN 类型的关系。

MATCH (a:Movie {title: 'Wall Street'})
OPTIONAL MATCH (x)-[r:ACTED_IN]->(a)
RETURN a.title, x.name, type(r)
表 7. 结果
a.title x.name type(r)

"Wall Street"

"Michael Douglas"

"ACTED_IN"

"Wall Street"

"Martin Sheen"

"ACTED_IN"

"Wall Street"

"Charlie Sheen"

"ACTED_IN"

行数:3