Cypher中多个match表示pipe效果 一个match查询结果给另外一个match使用

发布时间 2023-08-09 15:09:50作者: bonelee

https://neo4j.com/docs/cypher-manual/current/clauses/optional-match/

OPTIONAL MATCH

Introduction

OPTIONAL MATCH matches patterns against a graph database, just as MATCH does. The difference is that if no matches are found, OPTIONAL MATCH will use a null for missing parts of the pattern. OPTIONAL MATCH could therefore be considered the Cypher® equivalent of the outer join in SQL.

When using OPTIONAL MATCH, either the whole pattern is matched, or nothing is matched. The WHERE clause is part of the pattern description, and its predicates will be considered while looking for matches, not after. This matters especially in the case of multiple (OPTIONALMATCH clauses, where it is crucial to put WHERE together with the MATCH it belongs to.

To understand the patterns used in the OPTIONAL MATCH clause, read Patterns.

OPTIONAL MATCH就像将模式与图形数据库进行匹配一样MATCH不同之处在于,如果未找到匹配项,OPTIONAL MATCH将使用 null来表示模式中缺失的部分。 OPTIONAL MATCH因此,可以将 Cypher ®视为SQL 中外连接的等价物。

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

Example graph

The following graph is used for the examples below:

graph optional match clause

To recreate the graph, run the following query in an empty Neo4j database:

 
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 in more detail

Like SQL, Cypher queries are constructed using various clauses which are chained together to feed intermediate results between each other. For example, the matching variables from one MATCH clause will provide the context in which the next clause exists. However, there are two important differences between Neo4j and SQL which helps to explain OPTIONAL MATCH further.

  1. While it is both possible and advised to enforce partial schemas using indexes and constraints, Neo4j offers a greater degree of schema flexibility than a relational database. Nodes and relationships in a Neo4j database do not have to have a specific property set to them because other nodes or relationships in the same graph have that property (unless there is a existence constraint created on the specific property).

  2. Queries in Cypher are run as pipelines. If a clause returns no results, it will effectively end the query as subsequent clauses will have no data to execute upon.

For example, the following query returns no results:

与 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)

This is because the second MATCH clause returns no data (there are no DIRECTED relationships connected to Martin Sheen in the graph) to pass on to the RETURN clause.

However, replacing the second MATCH clause with OPTIONAL MATCH does return results. This is because, unlike MATCHOPTIONAL MATCH enables the value null to be passed between clauses.

 

这是因为第二个MATCH子句没有返回任何数据(图中没有DIRECTED连接到的关系Martin Sheen)以传递到该RETURN子句。

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

 

MATCH (p:Person {name: 'Martin Sheen'})
OPTIONAL MATCH (p)-[r:DIRECTED]->()
RETURN p.name, r
Table 1. Result
p.namer

"Martin Sheen"

<null>

Rows: 1

OPTIONAL MATCH can therefore be used to check graphs for missing as well as existing values, and to pass on rows without any data to subsequent clauses in a query.

Optional relationships

If the existence of a relationship is optional, use the OPTIONAL MATCH clause. If the relationship exists, it is returned. If it does not, null is returned in its place.

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

Returns null, since the Movie node Wall Street has no outgoing relationships.

Table 2. Result
x

<null>

Rows: 1

On the other hand, the following query does not return null since the Person node Charlie Sheen has one outgoing relationship.

 
MATCH (a:Person {name: 'Charlie Sheen'})
OPTIONAL MATCH (a)-->(x)
RETURN x   见上面的图即可知道答案是wall street
Table 3. Result
x

{"title":"Wall Street"}

Rows: 2

Properties on optional elements

If the existence of a property is optional, use the OPTIONAL MATCH clause. null will be returned if the specified property does not exist.

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

Returns the element x (null in this query), and null for its name property, because the Movie node Wall Street has no outgoing relationships.

Table 4. Result
xx.name

<null>

<null>

Rows: 1

The following query only returns null for the nodes which lack a name property.

 
MATCH (a:Person {name: 'Martin Sheen'})
OPTIONAL MATCH (a)-->(x)
RETURN x, x.name 见上图即知为啥有三个答案
Table 5. Result
xx.name

{"title":"Wall Street"}

<null>

{"name":"Charlie Sheen"}

"Charlie Sheen"

{"title":"The American President"}

<null>

Rows: 3

Optional typed and named relationship

It is also possible to look for specific relationship types when using OPTIONAL MATCH:

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

This returns the title of the Movie node Wall Street, and since this node has no outgoing ACTED_IN relationships, null is returned for the relationship denoted by the variable r.

Table 6. Result
a.titler

"Wall Street"

<null>

Rows: 1

However, the following query does not return null since it is looking for incoming relationships of the type ACTED_IN to the Movie node Wall Street.

 
MATCH (a:Movie {title: 'Wall Street'})
OPTIONAL MATCH (x)-[r:ACTED_IN]->(a)
RETURN a.title, x.name, type(r)
Table 7. Result
a.titlex.nametype(r)

"Wall Street"

"Michael Douglas"

"ACTED_IN"

"Wall Street"

"Martin Sheen"

"ACTED_IN"

"Wall Street"

"Charlie Sheen"

"ACTED_IN"

Rows: 3