12.2. Match

12.2.1. Introduction
12.2.2. Related nodes
12.2.3. Outgoing relationships
12.2.4. Directed relationships and identifier
12.2.5. Match by relationship type
12.2.6. Match by multiple relationship types
12.2.7. Match by relationship type and use an identifier
12.2.8. Relationship types with uncommon characters
12.2.9. Multiple relationships
12.2.10. Variable length relationships
12.2.11. Relationship identifier in variable length relationships
12.2.12. Zero length paths
12.2.13. Optional relationship
12.2.14. Optional typed and named relationship
12.2.15. Properties on optional elements
12.2.16. Complex matching
12.2.17. Shortest path
12.2.18. All shortest paths
12.2.19. Named path
12.2.20. Matching on a bound relationship
12.2.21. Match with OR

12.2.1. Introduction

[Tip]Tip

In the MATCH clause, patterns are used a lot. Read Section 11.5, “Patterns” for an introduction.

The following graph is used for the examples below:

Figure 12.2. Graph


12.2.2. Related nodes

The symbol -- means related to, without regard to type or direction.

Query. 

START n=node(3)
MATCH (n)--(x)
RETURN x

All nodes related to A (Anders) are returned by the query.

Result

x
3 rows

Node[4]{name:"Bossman"}

Node[1]{name:"David"}

Node[5]{name:"Cesar"}


Try this query live. (1) {"name":"David"} (2) {"name":"Emil"} (3) {"name":"Anders"} (4) {"name":"Bossman"} (5) {"name":"Cesar"} (1)-[:KNOWS]->(3) {} (3)-[:KNOWS]->(4) {} (3)-[:BLOCKS]->(5) {} (4)-[:KNOWS]->(2) {} (4)-[:BLOCKS]->(1) {} (5)-[:KNOWS]->(2) {} start n=node(3) match (n)--(x) return x

12.2.3. Outgoing relationships

When the direction of a relationship is interesting, it is shown by using --> or <--, like this:

Query. 

START n=node(3)
MATCH (n)-->(x)
RETURN x

All nodes that A has outgoing relationships to are returned.

Result

x
2 rows

Node[4]{name:"Bossman"}

Node[5]{name:"Cesar"}


Try this query live. (1) {"name":"David"} (2) {"name":"Emil"} (3) {"name":"Anders"} (4) {"name":"Bossman"} (5) {"name":"Cesar"} (1)-[:KNOWS]->(3) {} (3)-[:KNOWS]->(4) {} (3)-[:BLOCKS]->(5) {} (4)-[:KNOWS]->(2) {} (4)-[:BLOCKS]->(1) {} (5)-[:KNOWS]->(2) {} start n=node(3) match (n)-->(x) return x

12.2.4. Directed relationships and identifier

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. 

START n=node(3)
MATCH (n)-[r]->()
RETURN r

The query returns all outgoing relationships from node A.

Result

r
2 rows

:KNOWS[0] {}

:BLOCKS[1] {}


Try this query live. (1) {"name":"David"} (2) {"name":"Emil"} (3) {"name":"Anders"} (4) {"name":"Bossman"} (5) {"name":"Cesar"} (1)-[:KNOWS]->(3) {} (3)-[:KNOWS]->(4) {} (3)-[:BLOCKS]->(5) {} (4)-[:KNOWS]->(2) {} (4)-[:BLOCKS]->(1) {} (5)-[:KNOWS]->(2) {} start n=node(3) match (n)-[r]->() return r

12.2.5. Match by relationship type

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. 

START n=node(3)
MATCH (n)-[:BLOCKS]->(x)
RETURN x

All nodes that are BLOCKed by A are returned by this query.

Result

x
1 row

Node[5]{name:"Cesar"}


Try this query live. (1) {"name":"David"} (2) {"name":"Emil"} (3) {"name":"Anders"} (4) {"name":"Bossman"} (5) {"name":"Cesar"} (1)-[:KNOWS]->(3) {} (3)-[:KNOWS]->(4) {} (3)-[:BLOCKS]->(5) {} (4)-[:KNOWS]->(2) {} (4)-[:BLOCKS]->(1) {} (5)-[:KNOWS]->(2) {} start n=node(3) match (n)-[:BLOCKS]->(x) return x

12.2.6. Match by multiple relationship types

To match on one of multiple types, you can specify this by chaining them together with the pipe symbol |.

Query. 

START n=node(3)
MATCH (n)-[:BLOCKS|KNOWS]->(x)
RETURN x

All nodes with a BLOCK or KNOWS relationship to A are returned.

Result

x
2 rows

Node[5]{name:"Cesar"}

Node[4]{name:"Bossman"}


Try this query live. (1) {"name":"David"} (2) {"name":"Emil"} (3) {"name":"Anders"} (4) {"name":"Bossman"} (5) {"name":"Cesar"} (1)-[:KNOWS]->(3) {} (3)-[:KNOWS]->(4) {} (3)-[:BLOCKS]->(5) {} (4)-[:KNOWS]->(2) {} (4)-[:BLOCKS]->(1) {} (5)-[:KNOWS]->(2) {} start n=node(3) match (n)-[:BLOCKS|KNOWS]->(x) return x

12.2.7. Match by relationship type and use an identifier

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. 

START n=node(3)
MATCH (n)-[r:BLOCKS]->()
RETURN r

All BLOCKS relationships going out from A are returned.

Result

r
1 row

:BLOCKS[1] {}


Try this query live. (1) {"name":"David"} (2) {"name":"Emil"} (3) {"name":"Anders"} (4) {"name":"Bossman"} (5) {"name":"Cesar"} (1)-[:KNOWS]->(3) {} (3)-[:KNOWS]->(4) {} (3)-[:BLOCKS]->(5) {} (4)-[:KNOWS]->(2) {} (4)-[:BLOCKS]->(1) {} (5)-[:KNOWS]->(2) {} start n=node(3) match (n)-[r:BLOCKS]->() return r

12.2.8. Relationship types with uncommon characters

Sometime your database will have types with non-letter characters, or with spaces in them. Use ` (backtick) to quote these.

Query. 

START n=node(3)
MATCH (n)-[r:`TYPE THAT HAS SPACE IN IT`]->()
RETURN r

This query returns a relationship of a type with spaces in it.

Result

r
1 row

:TYPE THAT HAS SPACE IN IT[6] {}


Try this query live. (1) {"name":"David"} (2) {"name":"Emil"} (3) {"name":"Anders"} (4) {"name":"Bossman"} (5) {"name":"Cesar"} (1)-[:KNOWS]->(3) {} (3)-[:KNOWS]->(4) {} (3)-[:BLOCKS]->(5) {} (3)-[:TYPE THAT HAS SPACE IN IT]->(3) {} (4)-[:KNOWS]->(2) {} (4)-[:BLOCKS]->(1) {} (5)-[:KNOWS]->(2) {} start n=node(3) match (n)-[r:`TYPE THAT HAS SPACE IN IT`]->() return r

12.2.9. Multiple relationships

Relationships can be expressed by using multiple statements in the form of ()--(), or they can be strung together, like this:

Query. 

START a=node(3)
MATCH (a)-[:KNOWS]->(b)-[:KNOWS]->(c)
RETURN a,b,c

The three nodes in the path are returned by the query.

Result

abc
1 row

Node[3]{name:"Anders"}

Node[4]{name:"Bossman"}

Node[2]{name:"Emil"}


Try this query live. (1) {"name":"David"} (2) {"name":"Emil"} (3) {"name":"Anders"} (4) {"name":"Bossman"} (5) {"name":"Cesar"} (1)-[:KNOWS]->(3) {} (3)-[:KNOWS]->(4) {} (3)-[:BLOCKS]->(5) {} (4)-[:KNOWS]->(2) {} (4)-[:BLOCKS]->(1) {} (5)-[:KNOWS]->(2) {} start a=node(3) match (a)-[:KNOWS]->(b)-[:KNOWS]->(c) return a,b,c

12.2.10. 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.

Query. 

START a=node(3), x=node(2, 4)
MATCH a-[:KNOWS*1..3]->x
RETURN a,x

This query returns the start and end point, if there is a path between 1 and 3 relationships away.

Result

ax
2 rows

Node[3]{name:"Anders"}

Node[2]{name:"Emil"}

Node[3]{name:"Anders"}

Node[4]{name:"Bossman"}


Try this query live. (1) {"name":"David"} (2) {"name":"Emil"} (3) {"name":"Anders"} (4) {"name":"Bossman"} (5) {"name":"Cesar"} (1)-[:KNOWS]->(3) {} (3)-[:KNOWS]->(4) {} (3)-[:BLOCKS]->(5) {} (4)-[:KNOWS]->(2) {} (4)-[:BLOCKS]->(1) {} (5)-[:KNOWS]->(2) {} start a=node(3), x=node(2, 4) match a-[:KNOWS*1..3]->x return a,x

12.2.11. Relationship identifier in variable length relationships

When the connection between two nodes is of variable length, a relationship identifier becomes an collection of relationships.

Query. 

START a=node(3), x=node(2, 4)
MATCH a-[r:KNOWS*1..3]->x
RETURN r

The query returns the relationships, if there is a path between 1 and 3 relationships away.

Result

r
2 rows

[:KNOWS[0] {},:KNOWS[3] {}]

[:KNOWS[0] {}]


Try this query live. (1) {"name":"David"} (2) {"name":"Emil"} (3) {"name":"Anders"} (4) {"name":"Bossman"} (5) {"name":"Cesar"} (1)-[:KNOWS]->(3) {} (3)-[:KNOWS]->(4) {} (3)-[:BLOCKS]->(5) {} (4)-[:KNOWS]->(2) {} (4)-[:BLOCKS]->(1) {} (5)-[:KNOWS]->(2) {} start a=node(3), x=node(2, 4) match a-[r:KNOWS*1..3]->x return r

12.2.12. Zero length paths

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. 

START a=node(3)
MATCH p1=a-[:KNOWS*0..1]->b, p2=b-[:BLOCKS*0..1]->c
RETURN a,b,c, length(p1), length(p2)

This query will return four paths, some of which have length zero.

Result

abclength(p1)length(p2)
4 rows

Node[3]{name:"Anders"}

Node[3]{name:"Anders"}

Node[3]{name:"Anders"}

0

0

Node[3]{name:"Anders"}

Node[3]{name:"Anders"}

Node[5]{name:"Cesar"}

0

1

Node[3]{name:"Anders"}

Node[4]{name:"Bossman"}

Node[4]{name:"Bossman"}

1

0

Node[3]{name:"Anders"}

Node[4]{name:"Bossman"}

Node[1]{name:"David"}

1

1


Try this query live. (1) {"name":"David"} (2) {"name":"Emil"} (3) {"name":"Anders"} (4) {"name":"Bossman"} (5) {"name":"Cesar"} (1)-[:KNOWS]->(3) {} (3)-[:KNOWS]->(4) {} (3)-[:BLOCKS]->(5) {} (4)-[:KNOWS]->(2) {} (4)-[:BLOCKS]->(1) {} (5)-[:KNOWS]->(2) {} start a=node(3) match p1=a-[:KNOWS*0..1]->b, p2=b-[:BLOCKS*0..1]->c return a,b,c, length(p1), length(p2)

12.2.13. Optional relationship

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(2)
MATCH a-[?]->x
RETURN a,x

A node, and null are returned, since the node has no outgoing relationships.

Result

ax
1 row

Node[2]{name:"Emil"}

<null>


Try this query live. (1) {"name":"David"} (2) {"name":"Emil"} (3) {"name":"Anders"} (4) {"name":"Bossman"} (5) {"name":"Cesar"} (1)-[:KNOWS]->(3) {} (3)-[:KNOWS]->(4) {} (3)-[:BLOCKS]->(5) {} (4)-[:KNOWS]->(2) {} (4)-[:BLOCKS]->(1) {} (5)-[:KNOWS]->(2) {} start a=node(2) match a-[?]->x return a,x

12.2.14. Optional typed and named relationship

Just as with a normal relationship, you can decide which identifier it goes into, and what relationship type you need.

Query. 

START a=node(3)
MATCH a-[r?:LOVES]->()
RETURN a,r

This returns a node, and null, since the node has no outgoing LOVES relationships.

Result

ar
1 row

Node[3]{name:"Anders"}

<null>


Try this query live. (1) {"name":"David"} (2) {"name":"Emil"} (3) {"name":"Anders"} (4) {"name":"Bossman"} (5) {"name":"Cesar"} (1)-[:KNOWS]->(3) {} (3)-[:KNOWS]->(4) {} (3)-[:BLOCKS]->(5) {} (4)-[:KNOWS]->(2) {} (4)-[:BLOCKS]->(1) {} (5)-[:KNOWS]->(2) {} start a=node(3) match a-[r?:LOVES]->() return a,r

12.2.15. Properties on optional elements

Returning a property from an optional element that is null will also return null.

Query. 

START a=node(2)
MATCH a-[?]->x
RETURN x, x.name

This returns the element x (null in this query), and null as it’s name.

Result

xx.name
1 row

<null>

<null>


Try this query live. (1) {"name":"David"} (2) {"name":"Emil"} (3) {"name":"Anders"} (4) {"name":"Bossman"} (5) {"name":"Cesar"} (1)-[:KNOWS]->(3) {} (3)-[:KNOWS]->(4) {} (3)-[:BLOCKS]->(5) {} (4)-[:KNOWS]->(2) {} (4)-[:BLOCKS]->(1) {} (5)-[:KNOWS]->(2) {} start a=node(2) match a-[?]->x return x, x.name

12.2.16. Complex matching

Using Cypher, you can also express more complex patterns to match on, like a diamond shape pattern.

Query. 

START a=node(3)
MATCH (a)-[:KNOWS]->(b)-[:KNOWS]->(c), (a)-[:BLOCKS]-(d)-[:KNOWS]-(c)
RETURN a,b,c,d

This returns the four nodes in the paths.

Result

abcd
1 row

Node[3]{name:"Anders"}

Node[4]{name:"Bossman"}

Node[2]{name:"Emil"}

Node[5]{name:"Cesar"}


Try this query live. (1) {"name":"David"} (2) {"name":"Emil"} (3) {"name":"Anders"} (4) {"name":"Bossman"} (5) {"name":"Cesar"} (1)-[:KNOWS]->(3) {} (3)-[:KNOWS]->(4) {} (3)-[:BLOCKS]->(5) {} (4)-[:KNOWS]->(2) {} (4)-[:BLOCKS]->(1) {} (5)-[:KNOWS]->(2) {} start a=node(3) match (a)-[:KNOWS]->(b)-[:KNOWS]->(c), (a)-[:BLOCKS]-(d)-[:KNOWS]-(c) return a,b,c,d

12.2.17. Shortest path

Finding a single shortest path between two nodes is as easy as using the shortestPath function. It’s done like this:

Query. 

START d=node(1), e=node(2)
MATCH p = shortestPath( d-[*..15]->e )
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

[Node[1]{name:"David"},:KNOWS[2] {},Node[3]{name:"Anders"},:KNOWS[0] {},Node[4]{name:"Bossman"},:KNOWS[3] {},Node[2]{name:"Emil"}]


Try this query live. (1) {"name":"David"} (2) {"name":"Emil"} (3) {"name":"Anders"} (4) {"name":"Bossman"} (5) {"name":"Cesar"} (1)-[:KNOWS]->(3) {} (3)-[:KNOWS]->(4) {} (3)-[:BLOCKS]->(5) {} (4)-[:KNOWS]->(2) {} (4)-[:BLOCKS]->(1) {} (5)-[:KNOWS]->(2) {} start d=node(1), e=node(2) match p = shortestPath( d-[*..15]->e ) return p

12.2.18. All shortest paths

Finds all the shortest paths between two nodes.

Query. 

START d=node(1), e=node(2)
MATCH p = allShortestPaths( d-[*..15]->e )
RETURN p

This example will find the two directed paths between David and Emil.

Result

p
2 rows

[Node[1]{name:"David"},:KNOWS[2] {},Node[3]{name:"Anders"},:KNOWS[0] {},Node[4]{name:"Bossman"},:KNOWS[3] {},Node[2]{name:"Emil"}]

[Node[1]{name:"David"},:KNOWS[2] {},Node[3]{name:"Anders"},:BLOCKS[1] {},Node[5]{name:"Cesar"},:KNOWS[4] {},Node[2]{name:"Emil"}]


Try this query live. (1) {"name":"David"} (2) {"name":"Emil"} (3) {"name":"Anders"} (4) {"name":"Bossman"} (5) {"name":"Cesar"} (1)-[:KNOWS]->(3) {} (3)-[:KNOWS]->(4) {} (3)-[:BLOCKS]->(5) {} (4)-[:KNOWS]->(2) {} (4)-[:BLOCKS]->(1) {} (5)-[:KNOWS]->(2) {} start d=node(1), e=node(2) match p = allShortestPaths( d-[*..15]->e ) return p

12.2.19. Named path

If you want to return or filter on a path in your pattern graph, you can a introduce a named path.

Query. 

START a=node(3)
MATCH p = a-->b
RETURN p

This returns the two paths starting from the first node.

Result

p
2 rows

[Node[3]{name:"Anders"},:KNOWS[0] {},Node[4]{name:"Bossman"}]

[Node[3]{name:"Anders"},:BLOCKS[1] {},Node[5]{name:"Cesar"}]


Try this query live. (1) {"name":"David"} (2) {"name":"Emil"} (3) {"name":"Anders"} (4) {"name":"Bossman"} (5) {"name":"Cesar"} (1)-[:KNOWS]->(3) {} (3)-[:KNOWS]->(4) {} (3)-[:BLOCKS]->(5) {} (4)-[:KNOWS]->(2) {} (4)-[:BLOCKS]->(1) {} (5)-[:KNOWS]->(2) {} start a=node(3) match p = a-->b return p

12.2.20. Matching on a bound relationship

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. 

START r=rel(0)
MATCH a-[r]-b
RETURN a,b

This returns the two connected nodes, once as the start node, and once as the end node.

Result

ab
2 rows

Node[3]{name:"Anders"}

Node[4]{name:"Bossman"}

Node[4]{name:"Bossman"}

Node[3]{name:"Anders"}


Try this query live. (1) {"name":"David"} (2) {"name":"Emil"} (3) {"name":"Anders"} (4) {"name":"Bossman"} (5) {"name":"Cesar"} (1)-[:KNOWS]->(3) {} (3)-[:KNOWS]->(4) {} (3)-[:BLOCKS]->(5) {} (4)-[:KNOWS]->(2) {} (4)-[:BLOCKS]->(1) {} (5)-[:KNOWS]->(2) {} start r=rel(0) match a-[r]-b return a,b

12.2.21. Match with OR

Strictly speaking, you can’t do OR in your MATCH. It’s still possible to form a query that works a lot like OR.

Query. 

START a=node(3), b=node(2)
MATCH a-[?:KNOWS]-x-[?:KNOWS]-b
RETURN x

This query is saying: give me the nodes that are connected to a, or b, or both.

Result

x
3 rows

Node[4]{name:"Bossman"}

Node[5]{name:"Cesar"}

Node[1]{name:"David"}


Try this query live. (1) {"name":"David"} (2) {"name":"Emil"} (3) {"name":"Anders"} (4) {"name":"Bossman"} (5) {"name":"Cesar"} (1)-[:KNOWS]->(3) {} (3)-[:KNOWS]->(4) {} (3)-[:BLOCKS]->(5) {} (4)-[:KNOWS]->(2) {} (4)-[:BLOCKS]->(1) {} (5)-[:KNOWS]->(2) {} start a=node(3), b=node(2) match a-[?:KNOWS]-x-[?:KNOWS]-b return x