WHERE

The WHERE clause is not a clause in its own right — rather, it is subclause used with MATCH, OPTIONAL MATCH, and WITH clauses.

When used with MATCH and OPTIONAL MATCH, WHERE adds constraints to the patterns described. It should not be seen as a filter after the matching is finished.

In the case of multiple MATCH / OPTIONAL MATCH clauses, the predicate in WHERE is always a part of the patterns in the directly preceding MATCH / OPTIONAL MATCH. Both results and performance may be impacted if WHERE is put inside the wrong MATCH clause.

When used after WITH, WHERE simply filters the results.

For more uses of WHERE, see Predicates.

Example graph

The following graph is used for the examples below:

graph where clause

To recreate the graph, run the following query in an empty Neo4j database:

CREATE (andy:Swedish:Person {name: 'Andy', age: 36}),
       (timothy:Person {name: 'Timothy', age: 38}),
       (peter:Person {name: 'Peter', age: 35}),
       (lisa:Person {name: 'Lisa', age: 48}),
       (john:Person {name: 'John', age: 40}),
       (susan:Person {name: 'Susan', age: 32}),
       (andy)-[:KNOWS {since: 2012}]->(timothy),
       (andy)-[:KNOWS {since: 1999}]->(peter),
       (peter)-[:KNOWS {since: 2005}]->(lisa),
       (lisa)-[:KNOWS {since: 2010}]->(john),
       (john)-[:KNOWS {since: 2021}]->(susan)

Basic filtering

Filter on a node label
MATCH (n)
WHERE n:Swedish
RETURN n.name AS name
Result
name

"Andy"

Rows: 1

Filter on a node property
MATCH (n:Person)
WHERE n.age < 35
RETURN n.name AS name, n.age AS age
Result
name age

"Susan"

32

Rows: 1

Filter on a relationship property
MATCH (:Person {name:'Andy'})-[k:KNOWS]->(f)
WHERE k.since < 2000
RETURN f.name AS oldFriend
Result
oldFriend

"Peter"

Rows: 1

Filter on dynamic properties

To filter on a property using a dynamically computed name, use square brackets []:

Parameters
{
  "propname": "age"
}
Filter on a dynamically computed node property
MATCH (n:Person)
WHERE n[$propname] > 40
RETURN n.name AS name, n.age AS age
Result
name age

"Lisa"

48

Rows: 1

Using WHERE after WITH

WITH can be used to manipulate the output of a clause before it is passed on to subsequent query parts. Once such a manipulation has occurred, the original clause output is not available to subsequent clauses. For example, in the below query, WITH manipulates the output of the preceding MATCH in such a way that the succeeding RETURN no longer has access to the variable n declared in the MATCH.

WITH only retains explicitly listed variables; others become inaccessible
MATCH (n:Person)
WITH n.name as name
RETURN n

The above query would work if the RETURN clause instead referenced the name variable produced by WITH. However, because WHERE is a subclause and not a clause, its scope is not limited by immediately preceding WITH clauses.

WHERE is not limited by an immediately preceding WITH
MATCH (n:Person)
WITH n.name as name
WHERE n.age = 38
RETURN name
Result
name

"Timothy"

Rows: 1

The name for Timothy is returned because the WHERE clause still acts as a filter on the MATCH. However, WITH still reduces the scope for the rest of the query moving forward. In this case, name is the only variable in scope for the RETURN clause.

Filter patterns

WHERE clauses can be added to fixed-length and variable-length patterns in order to specify additional constraints.

Fixed-length patterns

WHERE inside a node pattern
WITH 35 AS minAge
MATCH (a:Person WHERE a.name = 'Andy')-[:KNOWS]->(b:Person WHERE b.age > minAge)
RETURN b.name AS name
Result
name

"Timothy"

Rows: 1

When used this way, predicates in WHERE can reference the node variable that the WHERE clause belongs to, but not other elements of the MATCH pattern.

The same rule applies to pattern comprehensions:

WHERE inside a pattern comprehension
MATCH (a:Person {name: 'Andy'})
RETURN [(a)-->(b WHERE b:Person) | b.name] AS friends
Result
friends

["Peter","Timothy"]

Rows: 1

WHERE can also appear inside a relationship pattern in a MATCH clause:

WHERE inside relationship pattern
WITH 2000 AS minYear
MATCH (a:Person)-[r:KNOWS WHERE r.since < minYear]->(b:Person)
RETURN a.name AS person, b.name AS friend, r.since AS knowsSince
Result
name friend knowsSince

"Andy"

"Peter"

1999

Rows: 1

Relationship pattern predicates can also be used inside pattern comprehensions, where the same caveats apply:

Relationship pattern predicate inside a pattern comprehension
WITH 2000 AS minYear
MATCH (a:Person {name: 'Andy'})
RETURN [(a)-[r:KNOWS WHERE r.since < minYear]->(b:Person) | r.since] AS years
Result
years

[1999]

Rows: 1

Variable-length patterns

If matching for variable length patterns, WHERE can only be used together with the quantified path pattern or quantified relationships syntax.

Allowed - WHERE predicate inside a quantified relationship
MATCH p = (a:Person {name: "Andy"})-[r:KNOWS WHERE r.since < 2011]->{1,4}(:Person)
RETURN [n IN nodes(p) | n.name] AS paths

Note that any path´s including Timothy and Susan are excluded by the WHERE predicate, since their incoming KNOWS relationships both have a since value that is higher than 2011.

Result
paths

["Andy", "Peter"]

["Andy", "Peter", "Lisa"]

["Andy", "Peter", "Lisa", "John"]

Rows: 3

For more information about using WHERE predicates in quantified path patterns, see Predicated in quantified path patterns.

WHERE is not allowed in variable-length patterns using the non-GQL compliant variable-length relationship syntax.

Not allowed - WHERE inside a variable-length relationship
MATCH p = (a:Person {name: 'Andy'})-[r:KNOWS*1..4 WHERE r.since < 2011]->(b:Person)
RETURN [n IN nodes(p) | n.name] AS path