OPTIONAL MATCH

介绍

OPTIONAL MATCH 子句用于匹配图数据库中的模式,与 MATCH 子句类似。区别在于,如果没有找到匹配项,OPTIONAL MATCH 将对模式中缺失的部分使用 null。因此,OPTIONAL MATCH 可被视为 Cypher® 中与 SQL 外连接等效的功能。

使用 OPTIONAL MATCH 时,要么整个模式都被匹配,要么不匹配任何内容。WHERE 子句是模式描述的一部分,其谓词将在查找匹配项时被考虑,而不是之后。这在存在多个(OPTIONALMATCH 子句的情况下尤为重要,此时将 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 子句。

然而,用 OPTIONAL MATCH 替换第二个 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 StreetACTED_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

© . All rights reserved.