The MATCH
clause allows you to specify the pattern Cypher will search for in the database.
Nodes and relationships that are already known at this stage are called bound pattern elements.
Cypher will now try to find the unknown parts of the pattern.
If MATCH
is the first clause in your query, nothing is bound at this stage.
Cypher needs start points to do it’s pattern matching.
If no bound nodes exist, Cypher can scan all nodes in the database, all nodes with a certain label, or it can use indexes to quickly find the relevant start points.
If you want to use index hints to force Cypher to use a specific index, read more here: Section 12.3, “Using”.
After finding start points — either by using scans, indexes or already bound points, the execution engine will use pattern matching to find matching sub graphs.
Because Cypher is declarative, it can change order of these operations.
WHERE
predicates can be evaluated before pattern matching, or during pattern matching, not only filtering after finding matches.
![]() | Tip |
---|---|
In the |
The following graph is used for the examples below:
By just specifying a pattern with a single node and no labels, all nodes in the graph will be returned.
Query.
MATCH n RETURN n
Returns all the nodes in the database.
Result
n |
---|
7 rows |
|
|
|
|
|
|
|
Getting all nodes with a label on them is done with a single node pattern where the node has a label on it.
Query.
MATCH movie:Movie RETURN movie
Returns all the movies in the database.
Result
movie |
---|
2 rows |
|
|
The symbol --
means related to, without regard to type or direction.
Query.
MATCH (director)--(movie) WHERE director.name='Oliver Stone' RETURN movie.title
Returns all the movies directed by Oliver Stone.
When the direction of a relationship is interesting, it is shown by using -->
or <--
, like this:
Query.
MATCH (martin)-->(movie) WHERE martin.name='Martin Sheen' RETURN movie.title
Returns nodes connected to Martin by outgoing relationships.
If an identifier is needed, either for filtering on properties of the relationship, or to return the relationship, this is how you introduce the identifier.
Query.
MATCH (martin)-[r]->(movie) WHERE martin.name='Martin Sheen' RETURN r
Returns all outgoing relationships from Martin.
When you know the relationship type you want to match on, you can specify it by using a colon together with the relationship type.
Query.
MATCH (wallstreet)<-[:ACTED_IN]-(actor) WHERE wallstreet.title='Wall Street' RETURN actor
Returns nodes that ACTED_IN
Wall Street.
Result
actor |
---|
3 rows |
|
|
|
To match on one of multiple types, you can specify this by chaining them together with the pipe symbol |
.
Query.
MATCH (wallstreet)<-[:ACTED_IN|:DIRECTED]-(person) WHERE wallstreet.title='Wall Street' RETURN person
Returns nodes with a ACTED_IN
or DIRECTED
relationship to Wall Street.
Result
person |
---|
4 rows |
|
|
|
|
If you both want to introduce an identifier to hold the relationship, and specify the relationship type you want, just add them both, like this.
Query.
MATCH (wallstreet)<-[r:ACTED_IN]-(actor) WHERE wallstreet.title='Wall Street' RETURN r
Returns nodes that ACTED_IN
Wall Street.
To constrain your pattern with labels on nodes, you add it to your pattern nodes, using the label syntax.
Query.
MATCH charlie:Person-->movie:Movie WHERE charlie.name='Charlie Sheen' RETURN movie
Return any nodes connected with Charlie that are labeled :Movie
Sometime your database will have types with non-letter characters, or with spaces in them. Use `
(backtick) to quote these.
Query.
MATCH (n)-[r:`TYPE THAT HAS SPACE IN IT`]->() WHERE n.name='Rob Reiner' RETURN r
Returns a relationship of a type with spaces in it.
Relationships can be expressed by using multiple statements in the form of ()--()
, or they can be strung together, like this:
Query.
MATCH (charlie)-[:ACTED_IN]->(movie)<-[:DIRECTED]->(director) WHERE charlie.name='Charlie Sheen' RETURN charlie,movie,director
Returns the three nodes in the path.
Result
charlie | movie | director |
---|---|---|
1 row | ||
|
|
|
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.
Query.
MATCH (martin)-[:ACTED_IN*1..2]-(x) WHERE martin.name='Martin Sheen' RETURN x
Returns nodes that are 1 or 2 relationships away from Martin.
Result
x |
---|
5 rows |
|
|
|
|
|
When the connection between two nodes is of variable length, a relationship identifier becomes an collection of relationships.
Query.
MATCH (actor)-[r:ACTED_IN*2]-(co_actor) WHERE actor.name='Charlie Sheen' RETURN r
The query returns a collection of relationships.
Using variable length paths that have the lower bound zero means that two identifiers can point to the same node. If the distance 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.
Query.
MATCH (wallstreet:Movie)-[*0..1]-(x) WHERE wallstreet.title='Wall Street' RETURN x
Returns all nodes that are zero or one relationships away from Wall Street.
Result
x |
---|
5 rows |
|
|
|
|
|
If a relationship is optional, it can be marked with a question mark. 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. Remember that anything hanging off an optional relationship, is in turn optional, unless it is connected with a bound node through some other path.
Query.
START a=node(5) MATCH a-[?]->x RETURN x
Returns null
, since the node has no outgoing relationships.
Just as with a normal relationship, you can decide which identifier it goes into, and what relationship type you need.
Query.
START a=node(5) MATCH a-[r?:ACTS_IN]->() RETURN r
This returns a node, and null
, since the node has no outgoing ACTS_IN
relationships.
Returning a property from an optional element that is null
will also return null
.
Query.
START a=node(5) MATCH a-[?]->x RETURN x, x.name
Returns the element x (null
in this query), and null
as its name.
Finding a single shortest path between two nodes is as easy as using the shortestPath
function. It’s done like this:
Query.
MATCH p = shortestPath( (martin:Person)-[*..15]-(oliver:Person) ) WHERE martin.name = 'Martin Sheen' and oliver.name = 'Oliver Stone' RETURN p
This means: find a single shortest path between two nodes, as long as the path is max 15 relationships long. Inside of the parenthesis you define a single link of a path — the starting node, the connecting relationship and the end node. Characteristics describing the relationship like relationship type, max hops and direction are all used when finding the shortest path. You can also mark the path as optional.
Result
p |
---|
1 row |
|
Finds all the shortest paths between two nodes.
Query.
START martin=node(3), michael=node(7) MATCH p = allShortestPaths( martin-[*]-michael ) RETURN p
Finds the two shortest paths between Martin and Michael.
Result
p |
---|
2 rows |
|
|
If you want to return or filter on a path in your pattern graph, you can a introduce a named path.
Query.
MATCH p = (michael)-->() WHERE michael.name='Michael Douglas' RETURN p
Returns the two paths starting from Michael.
Result
p |
---|
2 rows |
|
|
When your pattern contains a bound relationship, and that relationship pattern doesn’t specify direction, Cypher will try to match the relationship where the connected nodes switch sides.
Query.
MATCH a-[r]-b WHERE id(r) = 0 RETURN a,b
This returns the two connected nodes, once as the start node, and once as the end node.
Result
a | b |
---|---|
2 rows | |
|
|
|
|
Copyright © 2013 Neo Technology