The OPTIONAL MATCH
clause is used to search for the pattern described in it, while using NULL
s for missing parts of the pattern.
Introduction
OPTIONAL MATCH
matches patterns against your graph database, just like MATCH
does.
The difference is that if no matches are found, OPTIONAL MATCH
will use NULL
s for missing parts of the pattern.
OPTIONAL MATCH
could be considered the Cypher equivalent of the outer join in SQL.
Either the whole pattern is matched, or nothing is matched.
Remember that WHERE
is part of the pattern description, and the predicates will be considered while looking for matches, not after.
This matters especially in the case of multiple (OPTIONAL
) MATCH
clauses, where it is crucial to put WHERE
together with the MATCH
it belongs to.
Tip To understand the patterns used in the |
The following graph is used for the examples below:
Relationship
If a relationship is optional, use the OPTIONAL
MATCH
clause. This is similar to how a SQL outer join works. If the relationship is there, it is returned. If it’s not, NULL
is returned in it’s place.
Query
MATCH (a:Movie { title: 'Wall Street' }) OPTIONAL MATCH (a)-->(x) RETURN x
Returns NULL
, since the node has no outgoing relationships.
Result
x |
---|
1 row |
|
Try this query live create (_0:`Movie` {`name`:"WallStreet", `title`:"Wall Street"}) create (_1:`Person` {`name`:"Rob Reiner"}) create (_2:`Movie` {`name`:"TheAmericanPresident", `title`:"The American President"}) create (_3:`Person` {`name`:"Oliver Stone"}) create (_4:`Person` {`name`:"Charlie Sheen"}) create (_5:`Person` {`name`:"Michael Douglas"}) create (_6:`Person` {`name`:"Martin Sheen"}) create (_1)-[:`DIRECTED`]->(_2) create (_3)-[:`DIRECTED`]->(_0) create (_4)-[:`FATHER`]->(_6) create (_4)-[:`ACTED_IN`]->(_0) create (_5)-[:`ACTED_IN`]->(_2) create (_5)-[:`ACTED_IN`]->(_0) create (_6)-[:`ACTED_IN`]->(_2) create (_6)-[:`ACTED_IN`]->(_0) ; match (a:Movie {title: 'Wall Street'}) optional match (a)-->(x) return x
Properties on optional elements
Returning a property from an optional element that is NULL
will also return NULL
.
Query
MATCH (a:Movie { title: 'Wall Street' }) OPTIONAL MATCH (a)-->(x) RETURN x, x.name
Returns the element x (NULL
in this query), and NULL
as its name.
Result
x | x.name |
---|---|
1 row | |
|
|
Try this query live create (_0:`Movie` {`name`:"WallStreet", `title`:"Wall Street"}) create (_1:`Person` {`name`:"Rob Reiner"}) create (_2:`Movie` {`name`:"TheAmericanPresident", `title`:"The American President"}) create (_3:`Person` {`name`:"Oliver Stone"}) create (_4:`Person` {`name`:"Charlie Sheen"}) create (_5:`Person` {`name`:"Michael Douglas"}) create (_6:`Person` {`name`:"Martin Sheen"}) create (_1)-[:`DIRECTED`]->(_2) create (_3)-[:`DIRECTED`]->(_0) create (_4)-[:`FATHER`]->(_6) create (_4)-[:`ACTED_IN`]->(_0) create (_5)-[:`ACTED_IN`]->(_2) create (_5)-[:`ACTED_IN`]->(_0) create (_6)-[:`ACTED_IN`]->(_2) create (_6)-[:`ACTED_IN`]->(_0) ; match (a:Movie {title: 'Wall Street'}) optional match (a)-->(x) return x, x.name
Optional typed and named relationship
Just as with a normal relationship, you can decide which variable it goes into, and what relationship type you need.
Query
MATCH (a:Movie { title: 'Wall Street' }) OPTIONAL MATCH (a)-[r:ACTS_IN]->() RETURN r
This returns a node, and NULL
, since the node has no outgoing ACTS_IN
relationships.
Result
r |
---|
1 row |
|
Try this query live create (_0:`Movie` {`name`:"WallStreet", `title`:"Wall Street"}) create (_1:`Person` {`name`:"Rob Reiner"}) create (_2:`Movie` {`name`:"TheAmericanPresident", `title`:"The American President"}) create (_3:`Person` {`name`:"Oliver Stone"}) create (_4:`Person` {`name`:"Charlie Sheen"}) create (_5:`Person` {`name`:"Michael Douglas"}) create (_6:`Person` {`name`:"Martin Sheen"}) create (_1)-[:`DIRECTED`]->(_2) create (_3)-[:`DIRECTED`]->(_0) create (_4)-[:`FATHER`]->(_6) create (_4)-[:`ACTED_IN`]->(_0) create (_5)-[:`ACTED_IN`]->(_2) create (_5)-[:`ACTED_IN`]->(_0) create (_6)-[:`ACTED_IN`]->(_2) create (_6)-[:`ACTED_IN`]->(_0) ; match (a:Movie {title: 'Wall Street'}) optional match (a)-[r:ACTS_IN]->() return r