11.1. Match

The MATCH clause is used to search for the pattern described in it.

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 Section 9.6, “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 of 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 sub-graphs. 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 Section 14.1, “Indexes”, and more about specifying hints to force Neo4j to solve a query in a specific way in Section 15.4, “Using”.

[Tip]Tip

To understand more about the patterns used in the MATCH clause, read Section 9.6, “Patterns”

The following graph is used for the examples below:

Figure 11.1. Graph

Basic node finding

Get all nodes

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

Node[0]{name:"Charlie Sheen"}

Node[1]{name:"Martin Sheen"}

Node[2]{name:"Michael Douglas"}

Node[3]{name:"Oliver Stone"}

Node[4]{name:"Rob Reiner"}

Node[5]{title:"Wall Street"}

Node[6]{title:"The American President"}

Try this query live  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) MATCH (n) RETURN n

Get all nodes with a label

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

Returns all the movies in the database.

Result

movie.title

2 rows

"Wall Street"

"The American President"

Try this query live  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) MATCH (movie:Movie) RETURN movie.title

Match with labels

To constrain your pattern with labels on nodes, you add it to your pattern nodes, using the label syntax.

Query 

MATCH (:Person { name:'Oliver Stone' })--(movie:Movie)
RETURN movie.title

Returns any nodes connected with the Person Oliver that are labeled Movie.

Result

movie.title

1 row

"Wall Street"

Try this query live  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) MATCH (:Person { name:'Oliver Stone' })--(movie:Movie) RETURN movie.title

Relationship basics

Outgoing relationships

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

Query 

MATCH (:Person { name:'Oliver Stone' })-->(movie)
RETURN movie.title

Returns any nodes connected with the Person Oliver by an outgoing relationship.

Result

movie.title

1 row

"Wall Street"

Try this query live  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) MATCH (:Person { name:'Oliver Stone' })-->(movie) RETURN movie.title

Directed relationships and variable

If an variable is needed, either for filtering on properties of the relationship, or to return the relationship, this is how you introduce the variable.

Query 

MATCH (:Person { name:'Oliver Stone' })-[r]->(movie)
RETURN type(r)

Returns the type of each outgoing relationship from Oliver.

Result

type(r)

1 row

"DIRECTED"

Try this query live  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) MATCH (:Person { name:'Oliver Stone' })-[r]->(movie) RETURN type(r)

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 

MATCH (wallstreet:Movie { title:'Wall Street' })<-[:ACTED_IN]-(actor)
RETURN actor.name

Returns all actors that ACTED_IN Wall Street.

Result

actor.name

3 rows

"Michael Douglas"

"Martin Sheen"

"Charlie Sheen"

Try this query live  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) MATCH (wallstreet:Movie { title:'Wall Street' })<-[:ACTED_IN]-(actor) RETURN actor.name

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 

MATCH (wallstreet { title:'Wall Street' })<-[:ACTED_IN|:DIRECTED]-(person)
RETURN person.name

Returns nodes with an ACTED_IN or DIRECTED relationship to Wall Street.

Result

person.name

4 rows

"Oliver Stone"

"Michael Douglas"

"Martin Sheen"

"Charlie Sheen"

Try this query live  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) MATCH (wallstreet { title:'Wall Street' })<-[:ACTED_IN|:DIRECTED]-(person) RETURN person.name

Match by relationship type and use an variable

If you both want to introduce an variable to hold the relationship, and specify the relationship type you want, just add them both, like this:

Query 

MATCH (wallstreet { title:'Wall Street' })<-[r:ACTED_IN]-(actor)
RETURN r.role

Returns ACTED_IN roles for Wall Street.

Result

r.role

3 rows

"Gordon Gekko"

"Carl Fox"

"Bud Fox"

Try this query live  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) MATCH (wallstreet { title:'Wall Street' })<-[r:ACTED_IN]-(actor) RETURN r.role

Relationships in depth

[Note]Note

Inside a single pattern, relationships will only be matched once. You can read more about this in Section 8.4, “Uniqueness”.

Relationship types with uncommon characters

Sometimes your database will have types with non-letter characters, or with spaces in them. Use ` (backtick) to quote these. To demonstrate this we can add an additional relationship between Charlie Sheen and Rob Reiner:

Query 

MATCH (charlie:Person { name:'Charlie Sheen' }),(rob:Person { name:'Rob Reiner' })
CREATE (rob)-[:`TYPE
WITH SPACE`]->(charlie)

Which leads to the following graph:

Figure 11.2. Graph

Try this query live  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) MATCH (charlie:Person {name:'Charlie Sheen'}), (rob:Person {name:'Rob Reiner'}) CREATE (rob)-[:`TYPE WITH SPACE`]->(charlie)

Query 

MATCH (n { name:'Rob Reiner' })-[r:`TYPE
WITH SPACE`]->()
RETURN type(r)

Returns a relationship type with a space in it

Result

type(r)

1 row

"TYPE WITH SPACE"

Try this query live  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) MATCH (charlie:Person {name:'Charlie Sheen'}), (rob:Person {name:'Rob Reiner'}) CREATE (rob)-[:`TYPE WITH SPACE`]->(charlie) MATCH (n { name:'Rob Reiner' })-[r:`TYPE WITH SPACE`]->() RETURN type(r)

Multiple relationships

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

Query 

MATCH (charlie { name:'Charlie Sheen' })-[:ACTED_IN]->(movie)<-[:DIRECTED]-(director)
RETURN movie.title, director.name

Returns the movie Charlie acted in and its director.

Result

movie.titledirector.name

1 row

"Wall Street"

"Oliver Stone"

Try this query live  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) match (charlie {name:'Charlie Sheen'})-[:ACTED_IN]->(movie)<-[:DIRECTED]-(director) return movie.title, director.name

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 and this implies a fixed length pattern.

Query 

MATCH (martin { name:'Charlie Sheen' })-[:ACTED_IN*1..3]-(movie:Movie)
RETURN movie.title

Returns all movies related to Charlie by 1 to 3 hops.

Result

movie.title

3 rows

"Wall Street"

"The American President"

"The American President"

Try this query live  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) match (martin {name:'Charlie Sheen'})-[:ACTED_IN*1..3]-(movie:Movie) return movie.title

Relationship variable in variable length relationships

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

Query 

MATCH (actor { name:'Charlie Sheen' })-[r:ACTED_IN*2]-(co_actor)
RETURN r

Returns a collection of relationships.

Result

r

2 rows

[:ACTED_IN[0]{role:"Bud Fox"},:ACTED_IN[1]{role:"Carl Fox"}]

[:ACTED_IN[0]{role:"Bud Fox"},:ACTED_IN[2]{role:"Gordon Gekko"}]

Try this query live  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) MATCH (actor { name:'Charlie Sheen' })-[r:ACTED_IN*2]-(co_actor) RETURN r

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. In this query, there are two paths between Charlie Sheen and his father Martin Sheen. One of them includes a “blocked” relationship and the other doesn’t. In this case we first alter the original graph by using the following query to add “blocked” and “unblocked” relationships:

Query 

MATCH (charlie:Person { name:'Charlie Sheen' }),(martin:Person { name:'Martin Sheen' })
CREATE (charlie)-[:X { blocked:false }]->(:Unblocked)<-[:X { blocked:false }]-(martin)
CREATE (charlie)-[:X { blocked:true }]->(:Blocked)<-[:X { blocked:false }]-(martin)

This means that we are starting out with the following graph:

Figure 11.3. Graph

Try this query live  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) MATCH (charlie:Person {name:'Charlie Sheen'}), (martin:Person {name:'Martin Sheen'}) CREATE (charlie)-[:X {blocked:false}]->(:Unblocked)<-[:X {blocked:false}]-(martin) CREATE (charlie)-[:X {blocked:true}]->(:Blocked)<-[:X {blocked:false}]-(martin)

Query 

MATCH p =(charlie:Person)-[* { blocked:false }]-(martin:Person)
WHERE charlie.name = 'Charlie Sheen' AND martin.name = 'Martin Sheen'
RETURN p

Returns the paths between Charlie and Martin Sheen where all relationships have the blocked property set to FALSE.

Result

p

1 row

[Node[0]{name:"Charlie Sheen"},:X[7]{blocked:false},Node[7]{},:X[8]{blocked:false},Node[1]{name:"Martin Sheen"}]

Try this query live  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) MATCH (charlie:Person {name:'Charlie Sheen'}), (martin:Person {name:'Martin Sheen'}) CREATE (charlie)-[:X {blocked:false}]->(:Unblocked)<-[:X {blocked:false}]-(martin) CREATE (charlie)-[:X {blocked:true}]->(:Blocked)<-[:X {blocked:false}]-(martin) MATCH p = (charlie:Person)-[* {blocked:false}]-(martin:Person) WHERE charlie.name = 'Charlie Sheen' AND martin.name = 'Martin Sheen' RETURN p

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.

Query 

MATCH (wallstreet:Movie { title:'Wall Street' })-[*0..1]-(x)
RETURN x

Returns the movie itself as well as actors and directors one relationship away

Result

x

5 rows

Node[5]{title:"Wall Street"}

Node[0]{name:"Charlie Sheen"}

Node[1]{name:"Martin Sheen"}

Node[2]{name:"Michael Douglas"}

Node[3]{name:"Oliver Stone"}

Try this query live  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) MATCH (wallstreet:Movie { title:'Wall Street' })-[*0..1]-(x) RETURN x

Named path

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 { name:'Michael Douglas' })-->()
RETURN p

Returns the two paths starting from Michael

Result

p

2 rows

[Node[2]{name:"Michael Douglas"},:ACTED_IN[5]{role:"President Andrew Shepherd"},Node[6]{title:"The American President"}]

[Node[2]{name:"Michael Douglas"},:ACTED_IN[2]{role:"Gordon Gekko"},Node[5]{title:"Wall Street"}]

Try this query live  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) MATCH p =(michael { name:'Michael Douglas' })-->() RETURN p

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 in both directions.

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

ab

2 rows

Node[0]{name:"Charlie Sheen"}

Node[5]{title:"Wall Street"}

Node[5]{title:"Wall Street"}

Node[0]{name:"Charlie Sheen"}

Try this query live  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) MATCH (a)-[r]-(b) WHERE id(r)= 0 RETURN a,b

Shortest path

Single shortest path

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

Query 

MATCH (martin:Person { name:"Martin Sheen" }),(oliver:Person { name:"Oliver Stone" }), p = shortestPath((martin)-[*..15]-(oliver))
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 parentheses 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. 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 Section 16.6, “Shortest path planning”).

Result

p

1 row

[Node[1]{name:"Martin Sheen"},:ACTED_IN[1]{role:"Carl Fox"},Node[5]{title:"Wall Street"},:DIRECTED[3]{},Node[3]{name:"Oliver Stone"}]

Try this query live  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) MATCH (martin:Person {name:"Martin Sheen"} ), (oliver:Person {name:"Oliver Stone"}), p = shortestPath( (martin)-[*..15]-(oliver) ) RETURN p

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.

Query 

MATCH (charlie:Person { name:"Charlie Sheen" }),(martin:Person { name:"Martin Sheen" }), p = shortestPath((charlie)-[*]-(martin))
WHERE NONE (r IN rels(p) WHERE type(r)= "FATHER")
RETURN p

This query will find the shortest path between Charlie Sheen and Martin Sheen, and the WHERE predicate will ensure that we don’t consider the father/son relationship between the two.

Result

p

1 row

[Node[0]{name:"Charlie Sheen"},:ACTED_IN[0]{role:"Bud Fox"},Node[5]{title:"Wall Street"},:ACTED_IN[1]{role:"Carl Fox"},Node[1]{name:"Martin Sheen"}]

Try this query live  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) MATCH (charlie:Person {name:"Charlie Sheen"}), (martin:Person {name:"Martin Sheen"}), p = shortestPath( (charlie)-[*]-(martin) ) WHERE NONE(r in rels(p) WHERE type(r) = "FATHER") RETURN p

All shortest paths

Finds all the shortest paths between two nodes.

Query 

MATCH (martin:Person { name:"Martin Sheen" }),(michael:Person { name:"Michael Douglas" }), p = allShortestPaths((martin)-[*]-(michael))
RETURN p

Finds the two shortest paths between Martin and Michael.

Result

p

2 rows

[Node[1]{name:"Martin Sheen"},:ACTED_IN[1]{role:"Carl Fox"},Node[5]{title:"Wall Street"},:ACTED_IN[2]{role:"Gordon Gekko"},Node[2]{name:"Michael Douglas"}]

[Node[1]{name:"Martin Sheen"},:ACTED_IN[4]{role:"A.J. MacInerney"},Node[6]{title:"The American President"},:ACTED_IN[5]{role:"President Andrew Shepherd"},Node[2]{name:"Michael Douglas"}]

Try this query live  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) match (martin:Person {name:"Martin Sheen"} ), (michael:Person {name:"Michael Douglas"}), p = allShortestPaths( (martin)-[*]-(michael) ) return p

Get node or relationship by id

Node by id

Searching for nodes by id can be done with the id() function in a predicate.

[Note]Note

Neo4j reuses its internal ids when nodes and relationships are deleted. This means that applications using, and relying on internal Neo4j ids, are brittle or at risk of making mistakes. It is therefor recommended to rather use application generated ids.

Query 

MATCH (n)
WHERE id(n)= 0
RETURN n

The corresponding node is returned.

Result

n

1 row

Node[0]{name:"Charlie Sheen"}

Try this query live  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) match (n) where id(n) = 0 return n

Relationship by id

Search for relationships by id can be done with the id() function in a predicate.

This is not recommended practice. See the section called “Node by id” for more information on the use of Neo4j ids.

Query 

MATCH ()-[r]->()
WHERE id(r)= 0
RETURN r

The relationship with id 0 is returned.

Result

r

1 row

:ACTED_IN[0]{role:"Bud Fox"}

Try this query live  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) match ()-[r]->() where id(r) = 0 return r

Multiple nodes by id

Multiple nodes are selected by specifying them in an IN clause.

Query 

MATCH (n)
WHERE id(n) IN [0,3,5]
RETURN n

This returns the nodes listed in the IN expression.

Result

n

3 rows

Node[0]{name:"Charlie Sheen"}

Node[3]{name:"Oliver Stone"}

Node[5]{title:"Wall Street"}

Try this query live  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) match (n) where id(n) in [0,3,5] return n