MATCH clause

The MATCH clause is used to obtain data from the database by matching it to a given pattern.

  1. Matching nodes
    1.1. Get all nodes
    1.2. Get all nodes with a label
  2. Matching relationships
    2.1. Get all related nodes
    2.2. Get related nodes with a label
    2.3. Get related nodes with a directed relationship
    2.4. Get a relationship
    2.5. Matching on a relationship with a type
    2.6. Matching on relationships with multiple types
    2.7. Uncommon characters in relationship types
    2.8. Match with multiple relationships
  3. Matching with variable length relationships
    3.1. Variable length relationships
    3.2. Variable length relationships with multiple relationship types
    3.3. Returning multiple relationships with variable length
  4. Using multiple MATCH clauses
    4.1. Cartesian product of nodes
    4.2. Creating a list
💡

Each node and relationship gets a identifier generated during their initialization which is persisted through the durability mechanism.

Return it with the id() function.

Data Set

The following examples are executed with this data set. You can create this data set locally by executing the queries at the end of the page: Dataset queries.

Data set

1. Matching nodes

1.1. Get all nodes

Without specifying labels, the query will return all the nodes in a graph:

MATCH (n) 
RETURN n;

Output:

+-----------------------------------------------------------------------------------------------------+
| n                                                                                                   |
+-----------------------------------------------------------------------------------------------------+
| (:Country {continent: "Europe", language: "German", name: "Germany", population: 83000000})         |
| (:Country {continent: "Europe", language: "French", name: "France", population: 67000000})          |
| (:Country {continent: "Europe", language: "English", name: "United Kingdom", population: 66000000}) |
| (:Person {name: "John"})                                                                            |
| (:Person {name: "Harry"})                                                                           |
| (:Person {name: "Anna"})                                                                            |
+-----------------------------------------------------------------------------------------------------+

1.2. Get all nodes with a label

By specifying the label of a node, all the nodes with that label are returned:

MATCH (c:Country)
RETURN c;

Output:

+-----------------------------------------------------------------------------------------------------+
| c                                                                                                   |
+-----------------------------------------------------------------------------------------------------+
| (:Country {continent: "Europe", language: "German", name: "Germany", population: 83000000})         |
| (:Country {continent: "Europe", language: "French", name: "France", population: 67000000})          |
| (:Country {continent: "Europe", language: "English", name: "United Kingdom", population: 66000000}) |
+-----------------------------------------------------------------------------------------------------+

2. Matching relationships

2.1. Get all related nodes

By using the related to symbol --, nodes that have a relationship with the specified node can be returned. The symbol represents an undirected relationship which means the direction of the relationship is not taken into account.

MATCH (:Person {name: 'John'})--(n)
RETURN n;

Output:

+---------------------------------------------------------------------------------------------+
| n                                                                                           |
+---------------------------------------------------------------------------------------------+
| (:Person {name: "Anna"})                                                                    |
| (:Country {continent: "Europe", language: "French", name: "France", population: 67000000})  |
| (:Country {continent: "Europe", language: "German", name: "Germany", population: 83000000}) |
| (:Person {name: "Harry"})                                                                   |
+---------------------------------------------------------------------------------------------+

2.2. Get related nodes with a label

To only return related to nodes with a specific label you need to add it using the label syntax:

MATCH (:Person {name: 'John'})--(p:Person)
RETURN p;

Output:

+---------------------------+
| p                         |
+---------------------------+
| (:Person {name: "Harry"}) |
| (:Person {name: "Anna"})  |
+---------------------------+

2.3. Get related nodes with a directed relationship

The related to symbol -- can be extended by using:

  • --> to specify outgoing relationships,
  • <-- to specify ingoing relationships.
MATCH (:Country {name: 'France'})<--(p:Person)
RETURN p;

Output:

+--------------------------+
| p                        |
+--------------------------+
| (:Person {name: "John"}) |
+--------------------------+

2.4. Get a relationship

If you want to return the relationship between two nodes or a property of the relationship, a variable is required. A directed or undirected relationship can be used.

This query returns the relationship and its type:

MATCH (:Person {name: 'John'})-[r]->()
RETURN type(r);

Output:

+--------------+
| type(r)      |
+--------------+
| WORKING_IN   |
| LIVING_IN    |
| FRIENDS_WITH |
+--------------+

This query also returns the property date_of_start of the relationship:

MATCH (:Person {name: 'John'})-[r]->()
RETURN type(r), r.date_of_start;

Output:

+-----------------+-----------------+
| type(r)         | r.date_of_start |
+-----------------+-----------------+
| WORKING_IN      | 2014            |
| LIVING_IN       | 2014            |
| FRIENDS_WITH    | 2011            |
+-----------------+-----------------+

2.5. Matching on a relationship with a type

To return a relationship with a specified type you need to use the type syntax. A directed or undirected relationship can be used:

MATCH (p:Person {name: 'John'})-[:LIVING_IN]->(c)
RETURN c.name;

Output:

+---------+
| c.name  |
+---------+
| Germany |
+---------+

2.6. Matching on relationships with multiple types

To return relationships with any of the specified types, the types need to be chained together with the pipe symbol |:

MATCH (p:Person {name: 'John'})-[:LIVING_IN |:WORKING_IN]->(c)
RETURN c.name;

Output:

+---------+
| c.name  |
+---------+
| France  |
| Germany |
+---------+

2.7. Uncommon characters in relationship types

If a type has non-letter characters, like spaces, for example, the backtick symbol ` needs to be used to quote these. If the relationship type LIVING_IN had a space instead of an underscore, a possible query would look like this.

MATCH (:Country {name: 'France'})<-[r:`LIVING IN`]-()
RETURN r.name;

2.8. Match with multiple relationships

Multiple relationship statements can be specified in the query:

MATCH (:Country {name: 'France'})<-[l:WORKING_IN]-(p)-[w:LIVING_IN]->(:Country {name: 'Germany'})
RETURN p.name;

Output:

+--------+
| p.name |
+--------+
| John   |
+--------+

3. Matching with variable length relationships

3.1. Variable length relationships

If a node needs to be specified by its distance in relationship→node hops, the following syntax is used: -[:TYPE*minHops..maxHops]→. minHops and maxHops are optional and default to 1 and infinity respectively. The dots can be omitted if both are not specified or if only one is set which implies a fixed length pattern.

MATCH ({name: 'United Kingdom'})<-[:LIVING_IN*1..2]-(n)
RETURN n;

Output:

+---------------------------------------------------------------------------------------------+
| n                                                                                           |
+---------------------------------------------------------------------------------------------+
| (:Person {name: "Harry"})                                                                   |
| (:Person {name: "Anna"})                                                                    |
| (:Country {continent: "Europe", language: "German", name: "Germany", population: 83000000}) |
+---------------------------------------------------------------------------------------------+

3.2. Variable length relationships with multiple relationship types

If variable lengths are used with multiple stacked up relationship types, *minHops..maxHops applies to any combination of relationships:

MATCH ({name: 'United Kingdom'})<-[:WORKING_IN|FRIENDS_WITH*1..2]-(p:Person)
RETURN p;

Output:

+---------------------------+
| p                         |
+---------------------------+
| (:Person {name: "John"})  |
| (:Person {name: "Harry"}) |
| (:Person {name: "Anna"})  |
+---------------------------+

3.3. Returning multiple relationships with variable length

If a variable length is used, the list of relationships can be returned by adding variable= at the beginning of the MATCH clause:

MATCH p=({name: 'John'})<-[:FRIENDS_WITH*1..2]-()
RETURN relationships(p);

Output:

+----------------------------------------+
| relationships(p)                       |
+----------------------------------------+
| [[FRIENDS_WITH {date_of_start: 2012}]] |
+----------------------------------------+

4. Using multiple MATCH clauses

4.1. Cartesian product of nodes

To create a Cartesian product, match the nodes in two separate MATCH queries.

For example, the following query will match each person from the dataset with each European country from the dataset:

MATCH (p:Person)
MATCH (c:Country {continent: "Europe"})
RETURN p.name,c.name;

Output:

+------------------+------------------+
| p.name           | c.name           |
+------------------+------------------+
| "John"           | "Germany"        |
| "Harry"          | "Germany"        |
| "Anna"           | "Germany"        |
| "John"           | "France"         |
| "Harry"          | "France"         |
| "Anna"           | "France"         |
| "John"           | "United Kingdom" |
| "Harry"          | "United Kingdom" |
| "Anna"           | "United Kingdom" |
+------------------+------------------+

The query returns the Cartesian product of matched nodes. The output of the first MATCH clause is matched with each output of the second MATCH clause. In this case, each person from the dataset is matched with each European country.

4.2. Creating a list

If you want to create a list containing the results of different MATCH queries, you can achieve that with multiple MATCH clauses in one query:

MATCH (p:Person)
WITH COLLECT(p.name) as people
MATCH (c:Country {continent: "Europe"})
WITH people + COLLECT(c.name) as names
RETURN names;

Output:

+------------------------------------------------------------------+
| names                                                            |
+------------------------------------------------------------------+
| ["John", "Harry", "Anna", "Germany", "France", "United Kingdom"] |
+------------------------------------------------------------------+

The query returns a list of names of all people from the dataset concatenated with the names of all European countries.

⚠️

If any of the sets MATCH clause returns is empty, the whole output will be an empty list.

The following query will return an empty list:

MATCH (p:Person)
WITH COLLECT(p.name) as people
MATCH (c:Country {continent: "Asia"})
WITH people + COLLECT(c.name) as names
RETURN names;

Output:

+-------+
| names |
+-------+
| Null  |
+-------+

Since the dataset doesn't contain any nodes labeled as Country with a property continent with the value Asia, the second MATCH clause returns an empty dataset and therefore the output is also an empty list. To avoid getting an empty list as an output, due to any of the MATCH clauses returning an empty set, use OPTIONAL MATCH clause:

MATCH (p:Person)
WITH COLLECT(p.name) as people
OPTIONAL MATCH (c:Country {continent: "Asia"})
WITH people + COLLECT(c.name) as names
RETURN names;

Output:

+---------------------------+
| names                     |
+---------------------------+
| ["John", "Harry", "Anna"] |
+---------------------------+

The OPTIONAL MATCH clause bypasses the empty set and the query returns only non-empty sets. Therefore, the output of the query is a list containing only the results of the first MATCH clause.

Dataset Queries

We encourage you to try out the examples by yourself. You can get our data set locally by executing the following query block.

MATCH (n) DETACH DELETE n;
 
CREATE (c1:Country {name: 'Germany', language: 'German', continent: 'Europe', population: 83000000});
CREATE (c2:Country {name: 'France', language: 'French', continent: 'Europe', population: 67000000});
CREATE (c3:Country {name: 'United Kingdom', language: 'English', continent: 'Europe', population: 66000000});
 
MATCH (c1),(c2)
WHERE c1.name = 'Germany' AND c2.name = 'France'
CREATE (c2)<-[:WORKING_IN {date_of_start: 2014}]-(p:Person {name: 'John'})-[:LIVING_IN {date_of_start: 2014}]->(c1);
 
MATCH (c)
WHERE c.name = 'United Kingdom'
CREATE (c)<-[:WORKING_IN {date_of_start: 2014}]-(p:Person {name: 'Harry'})-[:LIVING_IN {date_of_start: 2013}]->(c);
 
MATCH (p1),(p2)
WHERE p1.name = 'John' AND p2.name = 'Harry'
CREATE (p1)-[:FRIENDS_WITH {date_of_start: 2011}]->(p2);
 
MATCH (p1),(p2)
WHERE p1.name = 'John' AND p2.name = 'Harry'
CREATE (p1)<-[:FRIENDS_WITH {date_of_start: 2012}]-(:Person {name: 'Anna'})-[:FRIENDS_WITH {date_of_start: 2014}]->(p2);
 
MATCH (p),(c1),(c2)
WHERE p.name = 'Anna' AND c1.name = 'United Kingdom' AND c2.name = 'Germany'
CREATE (c2)<-[:LIVING_IN {date_of_start: 2014}]-(p)-[:LIVING_IN {date_of_start: 2014}]->(c1);
 
MATCH (n)-[r]->(m) RETURN n,r,m;