Overview
The MATCH
statement allows you to specify graph patterns to search for within the graph. It is the fundamental statement for retrieving data from the graph and binding them to variables for use in subsequent parts of the query.
<match statement> ::=
[ "OPTIONAL" ] "MATCH" <graph pattern> [ <graph pattern yield clause> ]
<graph pattern yield clause> ::=
"YIELD" <graph pattern yield item> [ { "," <graph pattern yield item> }... ]
<graph pattern yield item> ::= <element variable> | <path variable>
Details
- You can use the keyword
OPTIONAL
withMATCH
. The key difference betweenMATCH
andOPTIONAL MATCH
is in their handling of non-matching patterns:MATCH
: If the pattern does not match, no records are returned.OPTIONAL MATCH
: If the pattern does not match, the query returns anull
value.
- The
MATCH
statement supports the WHERE clause to apply search conditions to the graph pattern. - The
MATCH
statement supports the graph pattern YIELD clause to select variables to allow exposure in subsequent parts of the query.
Example Graph
The following examples run against this graph:
To create this graph, run the following query against an empty graph:
INSERT (rowlock:User {_id: 'U01', name: 'rowlock'}),
(brainy:User {_id: 'U02', name: 'Brainy'}),
(purplechalk:User {_id: 'U03', name: 'purplechalk'}),
(mochaeach:User {_id: 'U04', name: 'mochaeach'}),
(lionbower:User {_id: 'U05', name: 'lionbower'}),
(c01:Club {_id: 'C01', since: 2005}),
(c02:Club {_id: 'C02', since: 2005}),
(rowlock)-[:Follows {createdOn: '2024-1-5'}]->(brainy),
(mochaeach)-[:Follows {createdOn: '2024-2-10'}]->(brainy),
(brainy)-[:Follows {createdOn: '2024-2-1'}]->(purplechalk),
(purplechalk)-[:Follows {createdOn: '2024-5-3'}]->(lionbower),
(brainy)-[:Joins {memberNo: 1}]->(c01),
(lionbower)-[:Joins {memberNo: 2}]->(c01),
(mochaeach)-[:Joins {memberNo: 9}]->(c02)
Matching All Nodes
To match all nodes, use a node pattern without label or property filters.
MATCH (n)
RETURN n
Result: n
_id | _uuid | schema | values |
---|---|---|---|
U05 | Sys-gen | User | {name: "lionbower"} |
U04 | Sys-gen | User | {name: "mochaeach"} |
U03 | Sys-gen | User | {name: "purplechalk"} |
U02 | Sys-gen | User | {name: "Brainy"} |
U01 | Sys-gen | User | {name: "rowlock"} |
C02 | Sys-gen | Club | {since: 2005} |
C01 | Sys-gen | Club | {since: 2005} |
Matching All Edges
To match all edges, use an edge pattern without label or property filters. Notice that an edge pattern can only be used with node patterns on both sides, forming a path pattern.
MATCH ()-[e]-()
RETURN e
Result: e
_uuid |
_from |
_to |
_from_uuid |
_to_uuid |
schema |
values |
---|---|---|---|---|---|---|
Sys-gen | U01 | U02 | UUID of U01 | UUID of U02 | Follows | {createdOn: "2024-01-05 00:00:00" } |
Sys-gen | U01 | U02 | UUID of U01 | UUID of U02 | Follows | {createdOn: "2024-01-05 00:00:00"} |
Sys-gen | U02 | U03 | UUID of U02 | UUID of U03 | Follows | {createdOn: "2024-02-01 00:00:00"} |
Sys-gen | U02 | U03 | UUID of U02 | UUID of U03 | Follows | {createdOn: "2024-02-01 00:00:00"} |
Sys-gen | U03 | U05 | UUID of U03 | UUID of U05 | Follows | {createdOn: "2024-05-03 00:00:00"} |
Sys-gen | U03 | U05 | UUID of U03 | UUID of U05 | Follows | {createdOn: "2024-05-03 00:00:00"} |
Sys-gen | U04 | U02 | UUID of U04 | UUID of U02 | Follows | {createdOn: "2024-02-10 00:00:00"} |
Sys-gen | U04 | U02 | UUID of U04 | UUID of U02 | Follows | {createdOn: "2024-02-10 00:00:00"} |
Sys-gen | U02 | C01 | UUID of U02 | UUID of C01 | Joins | {memberNo: 1} |
Sys-gen | U02 | C01 | UUID of U02 | UUID of C01 | Joins | {memberNo: 1} |
Sys-gen | U05 | C01 | UUID of U05 | UUID of C01 | Joins | {memberNo: 2} |
Sys-gen | U05 | C01 | UUID of U05 | UUID of C01 | Joins | {memberNo: 2} |
Sys-gen | U04 | C02 | UUID of U04 | UUID of C02 | Joins | {memberNo: 9} |
Sys-gen | U04 | C02 | UUID of U04 | UUID of C02 | Joins | {memberNo: 9} |
Since edge direction is not specified in the above query, each edge in the graph is returned twice. Two paths are considered distinct when their element sequences differ.
To return all edges without duplication in the graph, you can specify the edge direction explicitly either as outgoing (>
) or incoming (<
).
MATCH ()<-[e]-()
RETURN e
Result: e
_uuid |
_from |
_to |
_from_uuid |
_to_uuid |
schema |
values |
---|---|---|---|---|---|---|
Sys-gen | U01 | U02 | UUID of U01 | UUID of U02 | Follows | {createdOn: "2024-01-05 00:00:00" } |
Sys-gen | U02 | U03 | UUID of U02 | UUID of U03 | Follows | {createdOn: "2024-02-01 00:00:00"} |
Sys-gen | U03 | U05 | UUID of U03 | UUID of U05 | Follows | {createdOn: "2024-05-03 00:00:00"} |
Sys-gen | U04 | U02 | UUID of U04 | UUID of U02 | Follows | {createdOn: "2024-02-10 00:00:00"} |
Sys-gen | U02 | C01 | UUID of U02 | UUID of C01 | Joins | {memberNo: 1} |
Sys-gen | U05 | C01 | UUID of U05 | UUID of C01 | Joins | {memberNo: 2} |
Sys-gen | U04 | C02 | UUID of U04 | UUID of C02 | Joins | {memberNo: 9} |
Matching with Labels
Both node pattern and edge pattern support the label expression to specify one or multiple labels of nodes and edges.
This query retrieves all nodes labeled Club
:
MATCH (n:Club)
RETURN n
Result: n
_id | _uuid | schema | values |
---|---|---|---|
C02 | Sys-gen | Club | {since: 2005} |
C01 | Sys-gen | Club | {since: 2005} |
This query retrieves all nodes connected to Brainy
with outgoing edges labeled Follows
or Joins
:
MATCH (:User {name: 'Brainy'})-[:Follows|Joins]->(n)
RETURN n
Result: n
_id | _uuid | schema | values |
---|---|---|---|
U03 | Sys-gen | User | {name: "purplechalk"} |
C01 | Sys-gen | Club | {since: 2005} |
Matching with Key-Value Property Specification
Element property specification can be enclosed in node patterns and edge patterns which applies joint equalities to filter nodes and edges with key-value pairs.
This query retrieves nodes labeled Club
whose code
and since
have specific values:
MATCH (n:Club {_id: 'C01', since: 2005})
RETURN n
Result: n
_id | _uuid | schema | values |
---|---|---|---|
C01 | Sys-gen | Club | {since: 2005} |
This query retrieves the member of club C01
whose memberNo
is 1:
MATCH (:Club {code: 'C01'})<-[:Joins {memberNo: 1}]->(n)
RETURN n
Result: n
_id | _uuid | schema | values |
---|---|---|---|
U02 | Sys-gen | User | {name: "Brainy"} |
Matching with Abbreviated Edges
When edge labels and properties are not relevant, and variables are not needed for later reference, you can simplify by using abbreviated edge patterns. The direction of the edges can still be specified if required.
This query retrieves nodes connected with mochaeach
with any outgoing edges:
MATCH (:User {name: 'mochaeach'})->(n)
RETURN n
Result: n
_id | _uuid | schema | values |
---|---|---|---|
U02 | Sys-gen | User | {name: "Brainy"} |
C02 | Sys-gen | Club | {since: 2005} |
Matching Paths
This query retrieves the name
of users followed by mochaeach
, and the code
of clubs joined by those users:
MATCH p = (:User {name: 'mochaeach'})-[:Follows]->(:User)-[:Joins]->(:Club)
RETURN p
Result:
p |
---|
(:User {_id: "U04", name: "mochaeach"})-[:Follows {createdOn: "2024-2-10"}]->(:User {_id: "U02", name: "Brainy"})-[:Joins {memberNo: 1}]->(:Club {_id: "C01", since: 2005}) |
Matching with WHERE Clauses
The WHERE
clause can be optionally used within an element pattern, a parenthesized path expression, or immediately after a graph pattern when the graph pattern is used in the MATCH
statement to specify various search conditions.
Element Pattern WHERE Clause
This query retrieves 1-step paths with outgoing edges labeled Follows
, where the createdOn
property of egdes is greater than a specified date:
MATCH p = ()-[e:Follows WHERE e.createdOn > '2024-4-1']->()
RETURN p
Result:
p |
---|
(:User {_id: "U03", name: "purplechalk"})-[:Follows {createdOn: "2024-5-3"}]->(:User {_id: "U05", name: "lionbower"}) |
Parenthesized Path Pattern WHERE Clause
This query retrieves one- or two-step paths containing edges labeled Follows
, where the createdOn
property of those edges is smaller than the specified value:
MATCH p = (()-[e:Follows]->() WHERE e.createdOn < "2024-2-5"){1,2}
RETURN p
Result:
p |
---|
(:User {_id: "U01", name: "rowlock"})-[:Follows {createdOn: "2024-1-5"}]->(:User {_id: "U02", name: "Brainy"}) |
(:User {_id: "U01", name: "rowlock"})-[:Follows {createdOn: "2024-1-5"}]->(:User {_id: "U02", name: "Brainy"})-[:Follows {createdOn: "2024-2-1"}]->(:User {_id: "U03", name: "purplechalk"}) |
(:User {_id: "U02", name: "Brainy"})-[:Follows {createdOn: "2024-2-1"}]->(:User {_id: "U03", name: "purplechalk"}) |
Graph Pattern WHERE Clause
This query retrieves members of club C01
whose memberNo
is greater than 1:
MATCH (c:Club)<-[e:Joins]->(n)
WHERE c._id = 'C01' AND e.memberNo > 1
RETURN n
Result: n
_id | _uuid | schema | values |
---|---|---|---|
U05 | Sys-gen | User | {name: "lionbower"} |
Matching Quantified Paths
A quantified path pattern constructs a path in which either the entire path or a segment of it is repeated a specified number of times.
Using Quantified Edges
This query retrieves the distinct nodes related to lionbower
in 1 to 3 hops:
MATCH (:User {name: 'lionbower'})-[]-{1,3}(n)
RETURN DISTINCT n._id AS IDs
Result:
IDs |
---|
U03 |
U02 |
U01 |
U04 |
C01 |
Using Quantified Paths
This query retrieves paths that begin with one- or two-step subpaths containing edges labeled Follows
, where the createdOn
property of those edges is greater than the specified value, and these subpaths must connect to node C01
:
MATCH p = (()-[e:Follows]->() WHERE e.createdOn > "2024-1-31"){1,2}()-({_id:"C01"})
RETURN p
Result:
p |
---|
(:User {_id: "U02", name: "Brainy"})-[:Follows {createdOn: "2024-02-01"}]->(:User {_id: "U03", name: "purplechalk"})-[:Follows {createdOn: "2024-05-03"}]->(:User {_id: "U05", name: "lionbower"})-[:Joins {memberNo: 2}]->(:Club {_id: "C01",since: 2005}) |
(:User {_id: "U03", name: "purplechalk"})-[:Follows {createdOn: "2024-05-03"}]->(:User {_id: "U05", name: "lionbower"})-[:Joins {memberNo: 2}]->(:Club {_id: "C01",since: 2005}) |
(:User {_id: "U04", name: "mochaeach"})-[:Follows {createdOn: "2024-02-10"}]->(:User {_id: "U02", name: "Brainy"})-[:Joins {memberNo: 1}]->(:Club {_id: "C01",since: 2005}) |
Matching Shortest Paths
A shortest path between two nodes is the path that has the fewest edges.
This query retrieves all the shortest paths between lionbower
and purplechalk
within 5 hops:
MATCH p = ALL SHORTEST (n1:User)-[]-{,5}(n2:User)
WHERE n1.name = 'lionbower' AND n2.name = 'purplechalk'
RETURN p
Result:
p |
---|
(:User {_id: "U05", name: "lionbower"})-[:Follows {createdOn: "2024-5-3"}]->(:User {_id: "U03", name: "purplechalk"}) |
Matching Multiple Connected Paths
When the MATCH
statement contains two or more path patterns connected by the common element variables, the final result is produced by taking the equi-join on the common variables of the result sets from the different path patterns.
This query retrieves nodes labeled Club
, who is connected with nodes who have relationships with both rowlock
and purplechalk
:
MATCH ({name: 'rowlock'})-(x)-({name: 'purplechalk'}), (x)-[]-(y:Club)
RETURN y
Result: y
_id | _uuid | schema | values |
---|---|---|---|
C01 | Sys-gen | Club | {since: 2005} |
Matching Multiple Disconnected Paths
When the MATCH
statement contains two or more disconnected path patterns (i.e., no common element variables), the final result is produced by taking the Cartesian product of the result sets from the different path patterns.
This query retrieves nodes labeled Club
, and nodes labeled User
who follow others after 2024-2-1
:
MATCH (c:Club), (u:User)-[f:Follows WHERE f.createdOn > '2024-2-1']->()
RETURN c._id, u.name
Result:
c._id | u.name |
---|---|
C02 | mochaeach |
C02 | purplechalk |
C01 | mochaeach |
C01 | purplechalk |
OPTIONAL MATCH
Keeping Records for All Subqueries
In both queries below, the variable u
is first bound to three nodes (mocaheach
, rowlock
, and purplechalk
) connected to the Brainy
in a MATCH
statement. This variable u
is then referenced in the second MATCH
statement, which leads to subqueries. In each subquery, one node from u
is used to facilitate the path pattern matching. If a node does not result in a match, it will be excluded from subsequent parts of the query unless OPTIONAL MATCH
is used, which returns a value of null
instead.
MATCH (:User {name: "Brainy"})-[]-(u:User)
MATCH (u)-[:Joins]-(c:Club)
RETURN u.name, c._id
Result:
u.name | c._id |
---|---|
mochaeach | C02 |
MATCH (:User {name: "Brainy"})-[:Follows]-(u:User)
OPTIONAL MATCH (u)-[:Joins]-(c:Club)
RETURN u.name, c._id
Result:
u.name | c._id |
---|---|
purplechalk | null |
mochaeach | C02 |
rowlock | null |
Keeping the Query Running
In the case when a statement produces empty result, the query effectively halts at that point, as there is no data for subsequent statements to operate on.
In this query, the second MATCH
statement fails to find a match for purplechalk
joining a club, resulting in an empty working table. Consequently, the query terminates, and the subsequent MATCH
statement, which could have retrieved data, is not executed.
MATCH (n:User {name: "purplechalk"})
MATCH (n)-[:Joins]-(c:Club)
MATCH (m:User {name: "lionbower"})
RETURN n.name, c._id, m.name
Result: No Return Data
To prevent the query from terminating early, you can use OPTIONAL MATCH
as it enables the value null
to be passed to the next statement.
MATCH (n:User {name: "purplechalk"})
OPTIONAL MATCH (n)-[:Joins]-(c:Club)
MATCH (m:User {name: "lionbower"})
RETURN n.name, c._id, m.name
Result:
n.name | c._id | m.name |
---|---|---|
purplechalk | null |
lionbower |
Checking the Existence of Edges
This query returns users who have no followers:
MATCH (n:User)
OPTIONAL MATCH p = (n)<-[:Follows]-() WHERE p IS NULL
RETURN COLLECT_LIST(n.name) AS Names
Result:
Names |
---|
["mochaeach", "rowlock", "Brainy", "purplechalk", "lionbower"] |
Graph Pattern YIELD Clause
The graph pattern YIELD
clause can be optionally used to select variables to allow exposure in subsequent parts of the query.
MATCH (n:User)-[:Joins]->(c:Club)
YIELD c
RETURN *
Result: n
_id | _uuid | schema | values |
---|---|---|---|
C01 | Sys-gen | Club | {since: 2005} |
C02 | Sys-gen | Club | {since: 2005} |
C01 | Sys-gen | Club | {since: 2005} |