MATCH
Introduction
The MATCH
clause allows you to specify the patterns Neo4j will search for in the database.
This is the primary way of getting data into the current set of bindings.
It is worth reading up more on the specification of the patterns themselves in Patterns.
MATCH
is often coupled to a WHERE
part which adds restrictions, or predicates, to the MATCH
patterns, making them more specific.
The predicates are part of the pattern description, and should not be considered a filter applied only after the matching is done.
This means that WHERE
should always be put together with the MATCH
clause it belongs to.
MATCH
can occur at the beginning of the query or later, possibly after a WITH
.
If it is the first clause, nothing will have been bound yet, and Neo4j will design a search to find the results matching the clause and any associated predicates specified in any WHERE
part.
This could involve a scan of the database, a search for nodes having a certain label, or a search of an index to find starting points for the pattern matching.
Nodes and relationships found by this search are available as bound pattern elements, and can be used for pattern matching of paths.
They can also be used in any further MATCH
clauses, where Neo4j will use the known elements, and from there find further unknown elements.
Cypher is declarative, and so usually the query itself does not specify the algorithm to use to perform the search.
Neo4j will automatically work out the best approach to finding start nodes and matching patterns.
Predicates in WHERE
parts can be evaluated before pattern matching, during pattern matching, or after finding matches.
However, there are cases where you can influence the decisions taken by the query compiler.
Read more about indexes in Indexes for search performance, and more about specifying hints to force Neo4j to solve a query in a specific way in Planner hints and the USING keyword.
To understand more about the patterns used in the |
Example graph
The following graph is used for the examples below:
To recreate the graph, run the following query against 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 {role: 'Bud Fox'}]->(wallStreet),
(martin)-[:ACTED_IN {role: 'Carl Fox'}]->(wallStreet),
(michael)-[:ACTED_IN {role: 'Gordon Gekko'}]->(wallStreet),
(oliver)-[:DIRECTED]->(wallStreet),
(thePresident:Movie {title: 'The American President'}),
(martin)-[:ACTED_IN {role: 'A.J. MacInerney'}]->(thePresident),
(michael)-[:ACTED_IN {role: 'President Andrew Shepherd'}]->(thePresident),
(rob)-[:DIRECTED]->(thePresident),
(martin)-[:FATHER_OF]->(charlie)
Basic node finding
Get all nodes
By specifying a pattern with a single node and no labels, all nodes in the graph will be returned.
MATCH (n)
RETURN n
Returns all the nodes in the database.
n |
---|
|
|
|
|
|
|
|
Rows: 7 |
Get all nodes with a label
Find all nodes with a specific label:
MATCH (movie:Movie)
RETURN movie.title
Returns all the nodes with the Movie
label in the database.
movie.title |
---|
|
|
Rows: 2 |
Related nodes
The symbol --
means related to, without regard to type or direction of the relationship.
MATCH (director {name: 'Oliver Stone'})--(movie)
RETURN movie.title
Returns all the movies directed by Oliver Stone
.
movie.title |
---|
|
Rows: 1 |
Match with labels
To constrain a pattern with labels on nodes, add the labels to the nodes in the pattern.
MATCH (:Person {name: 'Oliver Stone'})--(movie:Movie)
RETURN movie.title
Returns any nodes with the Movie
label connected to Oliver Stone
.
movie.title |
---|
|
Rows: 1 |
Match with a label expression for the node labels
A match with an OR
expression for the node label returns the nodes that contains both the specified labels.
MATCH (n:Movie|Person)
RETURN n.name AS name, n.title AS title
name | title |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Rows: 7 |
Relationship basics
Outgoing relationships
When the direction of a relationship is of interest, it is shown by using -->
or <--
.
For example:
MATCH (:Person {name: 'Oliver Stone'})-->(movie)
RETURN movie.title
Returns any nodes connected by an outgoing relationship to the Person
node with the name
property set to Oliver Stone
.
movie.title |
---|
|
Rows: 1 |
Relationship variables
It is possible to introduce a variable to a pattern, either for filtering on relationship properties or to return a relationship. For example:
MATCH (:Person {name: 'Oliver Stone'})-[r]->(movie)
RETURN type(r)
Returns the type of each outgoing relationship from Oliver Stone
.
type(r) |
---|
|
Rows: 1 |
Match on an undirected relationship
When a pattern contains a bound relationship, and that relationship pattern does not specify direction, Cypher will try to match the relationship in both directions.
MATCH (a)-[:ACTED_IN {role: 'Bud Fox'}]-(b)
RETURN a, b
a | b |
---|---|
|
|
|
|
Rows: 2 |
Match on relationship type
When the relationship type to match on is known, it is possible to specify it by using a colon (:
) before the relationship type.
MATCH (wallstreet:Movie {title: 'Wall Street'})<-[:ACTED_IN]-(actor)
RETURN actor.name
Returns all actors who ACTED_IN
the movie Wall Street
.
actor.name |
---|
|
|
|
Rows: 3 |
Read more about relationship type expressions.
Match on multiple relationship types
It is possible to match on multiple relationship types by using the pipe symbol (|
).
For example:
MATCH (wallstreet {title: 'Wall Street'})<-[:ACTED_IN|DIRECTED]-(person)
RETURN person.name
Returns nodes with an ACTED_IN
or DIRECTED
relationship to the movie Wall Street
.
person.name |
---|
|
|
|
|
Rows: 4 |
Match on relationship type and use a variable
Variables and specific relationship types can be included in the same pattern. For example:
MATCH (wallstreet {title: 'Wall Street'})<-[r:ACTED_IN]-(actor)
RETURN r.role
Returns the ACTED_IN
roles for the movie Wall Street
.
r.role |
---|
|
|
|
Rows: 3 |
Relationships in depth
Relationships will only be matched once inside a single pattern. Read more about this in the section on uniqueness. |
Relationship types with uncommon characters
Databases occasionally contain relationship types including non-alphanumerical characters, or with spaces in them.
These are created using backticks (`
).
For example, the following query creates a relationship which contains a space (OLD FRIENDS
) between Martin Sheen
and Rob Reiner
.
MATCH
(martin:Person {name: 'Martin Sheen'}),
(rob:Person {name: 'Rob Reiner'})
CREATE (rob)-[:`OLD FRIENDS`]->(martin)
This leads to the following graph:
MATCH (n {name: 'Rob Reiner'})-[r:`OLD FRIENDS`]->()
RETURN type(r)
type(r) |
---|
|
Rows: 1 |
Multiple relationships
Relationships can be expressed by using multiple statements in the form of ()--()
, or they can be strung together.
For example:
MATCH (charlie {name: 'Charlie Sheen'})-[:ACTED_IN]->(movie)<-[:DIRECTED]-(director)
RETURN movie.title, director.name
Returns the movie in which Charlie Sheen
acted and its director.
movie.title | director.name |
---|---|
|
|
Rows: 1 |
Variable length relationships
Nodes that are a variable number of relationship->node
hops away can be found using the following syntax:
-[:TYPE*minHops..maxHops]->
.
minHops
and maxHops
are optional and default to 1 and infinity respectively.
When no bounds are given the dots may be omitted.
The dots may also be omitted when setting only one bound as this implies a fixed length pattern.
Variable length relationships can be planned with an optimisation under certain circumstances, see VarLength Expand Pruning query plan. |
MATCH (charlie {name: 'Charlie Sheen'})-[:ACTED_IN*1..3]-(movie:Movie)
RETURN movie.title
Returns all movies related to Charlie Sheen
by 1 to 3 hops:
-
Wall Street
is found through the direct connection, whereas the other two results are found viaMichael Douglas
andMartin Sheen
respectively. -
As this example demonstrates, variable length relationships do not impose any requirements on the intermediate nodes.
movie.title |
---|
|
|
|
Rows: 3 |
Variable length relationships with multiple relationship types
Variable length relationships can be combined with multiple relationship types.
In this case, *minHops..maxHops
applies to all relationship types as well as any combination of them.
MATCH (charlie {name: 'Charlie Sheen'})-[:ACTED_IN|DIRECTED*2]-(person:Person)
RETURN person.name
Returns all people related to Charlie Sheen
by 2 hops with any combination of the relationship types ACTED_IN
and DIRECTED
.
person.name |
---|
|
|
|
Rows: 3 |
Relationship variable in variable length relationships
When the connection between two nodes is of variable length, the list of relationships comprising the connection can be returned using the following syntax:
MATCH p = (actor {name: 'Charlie Sheen'})-[:ACTED_IN*2]-(co_actor)
RETURN relationships(p)
Returns a list of relationships.
relationships(p) |
---|
|
|
Rows: 2 |
Match with properties on a variable length path
A variable length relationship with properties defined on in it means that all relationships in the path must have the property set to the given value.
The following query adds two new paths between Charlie Sheen
and his father Martin Sheen
, where a lead
property is added to the ACTED_IN
relationships connecting them to the Movie
nodes No Code of Conduct
and Free Money
.
The query makes evident that both actors had a leading role in the movie No Code of Conduct
, but only Martin Sheen
had a leading role in the movie Free Money
.
MATCH
(charlie:Person {name: 'Charlie Sheen'}),
(martin:Person {name: 'Martin Sheen'})
CREATE (charlie)-[:ACTED_IN {role: 'Bud', lead: true}]->(:Movie {title: 'Free Money'})<-[:ACTED_IN {role:'New Warden', lead: false}]-(martin),
(charlie)-[:ACTED_IN {role: 'Jake Peterson', lead: true}]->(:Movie {title: 'No Code of Conduct'})<-[:ACTED_IN {role: 'Bill Peterson', lead: true}]-(martin)
This leads to the following graph:
MATCH p = (charlie:Person)-[* {lead: true}]-(martin:Person)
WHERE charlie.name = 'Charlie Sheen' AND martin.name = 'Martin Sheen'
RETURN p
The above query returns the paths between Charlie Sheen
and Martin Sheen
where all relationships have the lead
property set to true
.
The following graph and text are returned:
p |
---|
|
Rows: 1 |
Zero length paths
Using variable length paths that have the lower bound zero means that two variables can point to the same node. If the path length between two nodes is zero, they are by definition the same node. Note that when matching zero length paths the result may contain a match even when matching on a relationship type not in use.
MATCH (wallstreet:Movie {title: 'Wall Street'})-[*0..1]-(x)
RETURN x
Returns the movie itself as well as actors and directors one relationship away
x |
---|
|
|
|
|
|
Rows: 5 |
Named paths
It is possible to introduce a named path to return or filter on a path in the pattern graph. For example:
MATCH p = (michael {name: 'Michael Douglas'})-->()
RETURN p
This query returns the following graph and text, showing the two paths starting from Michael Douglas
.
p |
---|
|
|
Rows: 2 |
Shortest path
Single shortest path
Finding a single shortest path between two nodes can be done by using the shortestPath
function.
MATCH
(martin:Person {name: 'Martin Sheen'}),
(oliver:Person {name: 'Oliver Stone'}),
p = shortestPath((martin)-[*..15]-(oliver))
RETURN p
This query finds the shortest path between two nodes, as long as the path is max 15 relationships long.
The path link (the starting node, the connecting relationships, and the end node) is defined within the parentheses.
Characteristics describing the relationship like relationship type, max hops and direction are all used when finding the shortest path.
If there is a WHERE
clause following the match of a shortestPath
, relevant predicates will be included in the shortestPath
.
If the predicate is a none()
or all()
on the relationship elements of the path, it will be used during the search to improve performance (see Shortest path planning).
The query returns the following graph and text, showing the shortest possible path between the start node (Martin Sheen
) and the end node (Oliver Stone
):
p |
---|
|
Rows: 1 |
Single shortest path with predicates
Predicates used in the WHERE
clause that apply to the shortest path pattern are evaluated before deciding what the shortest matching path is.
MATCH
(rob:Person {name: 'Rob Reiner'}),
(thePresident:Movie {title: 'The American President'}),
p = shortestPath((rob)-[*]-(thePresident))
WHERE none(r IN relationships(p) WHERE type(r) = 'DIRECTED')
RETURN p
This query will find the shortest path between Person
node Rob Reiner
and the Movie
node The American President
, and the WHERE
predicate will ensure that any relationship with the type DIRECTED
is not considered.
It returns the following graph and text:
p |
---|
|
Rows: 1 |
All shortest paths
Finding all shortest paths between two nodes can be done by using the allShortestPaths
function:
MATCH
(martin:Person {name: 'Martin Sheen'} ),
(michael:Person {name: 'Michael Douglas'}),
p = allShortestPaths((martin)-[*]-(michael))
RETURN p
This query finds the two shortest paths between Martin Sheen
and Michael Douglas
.
It returns the following graph and text:
p |
---|
|
|
Rows: 2 |
Was this page helpful?