15.11. Where

15.11.1. Boolean operations
15.11.2. Filter on node property
15.11.3. Regular expressions
15.11.4. Escaping in regular expressions
15.11.5. Case insensitive regular expressions
15.11.6. Filtering on relationship type
15.11.7. Property exists
15.11.8. Default true if property is missing
15.11.9. Default false if property is missing
15.11.10. Filter on null values
15.11.11. Filter on patterns
15.11.12. Filter on patterns using NOT
15.11.13. IN operator

If you need filtering apart from the pattern of the data that you are looking for, you can add clauses in the WHERE part of the query.

Graph

cypher-where-graph.txt.svg

15.11.1. Boolean operations

You can use the expected boolean operators AND and OR, and also the boolean function NOT().

Query

START n=node(3, 1)
WHERE (n.age < 30 and n.name = "Tobias") or not(n.name = "Tobias")
RETURN n

This will return both nodes in the start clause.

Result

n
2 rows
0 ms

Node[3]{name:"Andres",age:36,belt:"white"}

Node[1]{name:"Tobias",age:25}


Try this query live. (1) {"age":25,"name":"Tobias"} (2) {"age":34,"name":"Peter"} (3) {"age":36,"belt":"white","name":"Andres"} (3)-[:KNOWS]->(1) {} (3)-[:KNOWS]->(2) {} start n=node(3, 1) where (n.age < 30 and n.name = "Tobias") or not(n.name = "Tobias") return n

15.11.2. Filter on node property

To filter on a property, write your clause after the WHERE keyword. Filtering on relationship properties works just the same way.

Query

START n=node(3, 1)
WHERE n.age < 30
RETURN n

The "Tobias" node will be returned.

Result

n
1 row
0 ms

Node[1]{name:"Tobias",age:25}


Try this query live. (1) {"age":25,"name":"Tobias"} (2) {"age":34,"name":"Peter"} (3) {"age":36,"belt":"white","name":"Andres"} (3)-[:KNOWS]->(1) {} (3)-[:KNOWS]->(2) {} start n=node(3, 1) where n.age < 30 return n

15.11.3. Regular expressions

You can match on regular expressions by using =~ "regexp", like this:

Query

START n=node(3, 1)
WHERE n.name =~ 'Tob.*'
RETURN n

The "Tobias" node will be returned.

Result

n
1 row
0 ms

Node[1]{name:"Tobias",age:25}


Try this query live. (1) {"age":25,"name":"Tobias"} (2) {"age":34,"name":"Peter"} (3) {"age":36,"belt":"white","name":"Andres"} (3)-[:KNOWS]->(1) {} (3)-[:KNOWS]->(2) {} start n=node(3, 1) where n.name =~ 'Tob.*' return n

15.11.4. Escaping in regular expressions

If you need a forward slash inside of your regular expression, escape it. Remember that back slash needs to be escaped in string literals

Query

START n=node(3, 1)
WHERE n.name =~ 'Some\\/thing'
RETURN n

No nodes match this regular expression.

Result

n
0 row
0 ms

(empty result)


Try this query live. (1) {"age":25,"name":"Tobias"} (2) {"age":34,"name":"Peter"} (3) {"age":36,"belt":"white","name":"Andres"} (3)-[:KNOWS]->(1) {} (3)-[:KNOWS]->(2) {} start n=node(3, 1) where n.name =~ 'Some\\/thing' return n

15.11.5. Case insensitive regular expressions

By pre-pending a regular expression with (?i), the whole expression becomes case insensitive.

Query

START n=node(3, 1)
WHERE n.name =~ '(?i)ANDR.*'
RETURN n

The node with name "Andres" is returned.

Result

n
1 row
0 ms

Node[3]{name:"Andres",age:36,belt:"white"}


Try this query live. (1) {"age":25,"name":"Tobias"} (2) {"age":34,"name":"Peter"} (3) {"age":36,"belt":"white","name":"Andres"} (3)-[:KNOWS]->(1) {} (3)-[:KNOWS]->(2) {} start n=node(3, 1) where n.name =~ '(?i)ANDR.*' return n

15.11.6. Filtering on relationship type

You can put the exact relationship type in the MATCH pattern, but sometimes you want to be able to do more advanced filtering on the type. You can use the special property TYPE to compare the type with something else. In this example, the query does a regular expression comparison with the name of the relationship type.

Query

START n=node(3)
MATCH (n)-[r]->()
WHERE type(r) =~ 'K.*'
RETURN r

This returns relationships that has a type whose name starts with K.

Result

r
2 rows
0 ms

:KNOWS[0] {}

:KNOWS[1] {}


Try this query live. (1) {"age":25,"name":"Tobias"} (2) {"age":34,"name":"Peter"} (3) {"age":36,"belt":"white","name":"Andres"} (3)-[:KNOWS]->(1) {} (3)-[:KNOWS]->(2) {} start n=node(3) match (n)-[r]->() where type(r) =~ 'K.*' return r

15.11.7. Property exists

To only include nodes/relationships that have a property, use the HAS() function and just write out the identifier and the property you expect it to have.

Query

START n=node(3, 1)
WHERE has(n.belt)
RETURN n

The node named "Andres" is returned.

Result

n
1 row
0 ms

Node[3]{name:"Andres",age:36,belt:"white"}


Try this query live. (1) {"age":25,"name":"Tobias"} (2) {"age":34,"name":"Peter"} (3) {"age":36,"belt":"white","name":"Andres"} (3)-[:KNOWS]->(1) {} (3)-[:KNOWS]->(2) {} start n=node(3, 1) where has(n.belt) return n

15.11.8. Default true if property is missing

If you want to compare a property on a graph element, but only if it exists, use the nullable property syntax. You can use a question mark if you want missing property to return true, like:

Query

START n=node(3, 1)
WHERE n.belt? = 'white'
RETURN n

This returns all nodes, even those without the belt property.

Result

n
2 rows
0 ms

Node[3]{name:"Andres",age:36,belt:"white"}

Node[1]{name:"Tobias",age:25}


Try this query live. (1) {"age":25,"name":"Tobias"} (2) {"age":34,"name":"Peter"} (3) {"age":36,"belt":"white","name":"Andres"} (3)-[:KNOWS]->(1) {} (3)-[:KNOWS]->(2) {} start n=node(3, 1) where n.belt? = 'white' return n

15.11.9. Default false if property is missing

When you need missing property to evaluate to false, use the exclamation mark.

Query

START n=node(3, 1)
WHERE n.belt! = 'white'
RETURN n

No nodes without the belt property are returned.

Result

n
1 row
0 ms

Node[3]{name:"Andres",age:36,belt:"white"}


Try this query live. (1) {"age":25,"name":"Tobias"} (2) {"age":34,"name":"Peter"} (3) {"age":36,"belt":"white","name":"Andres"} (3)-[:KNOWS]->(1) {} (3)-[:KNOWS]->(2) {} start n=node(3, 1) where n.belt! = 'white' return n

15.11.10. Filter on null values

Sometimes you might want to test if a value or an identifier is null. This is done just like SQL does it, with IS NULL. Also like SQL, the negative is IS NOT NULL, although NOT(IS NULL x) also works.

Query

START a=node(1), b=node(3, 2)
MATCH a<-[r?]-b
WHERE r is null
RETURN b

Nodes that Tobias is not connected to are returned.

Result

b
1 row
0 ms

Node[2]{name:"Peter",age:34}


Try this query live. (1) {"age":25,"name":"Tobias"} (2) {"age":34,"name":"Peter"} (3) {"age":36,"belt":"white","name":"Andres"} (3)-[:KNOWS]->(1) {} (3)-[:KNOWS]->(2) {} start a=node(1), b=node(3, 2) match a<-[r?]-b where r is null return b

15.11.11. Filter on patterns

Patterns are expressions in Cypher, expressions that return a collection of paths. Collection expressions are also predicates — an empty collection represents false, and a non-empty represents true.

So, patterns are not only expressions, they are also predicates. The only limitation to your pattern is that you must be able to express it in a single path. You can not use commas between multiple paths like you do in MATCH. You can achieve the same effect by combining multiple patterns with AND.

Note that you can not introduce new identifiers here. Although it might look very similar to the MATCH patterns, the WHERE clause is all about eliminating matched subgraphs. MATCH a-[*]->b is very different from WHERE a-[*]->b; the first will produce a subgraph for every path it can find between a and b, and the latter will eliminate any matched subgraphs where a and b do not have a directed relationship chain between them.

Query

START tobias=node(1), others=node(3, 2)
WHERE tobias<--others
RETURN others

Nodes that have an outgoing relationship to the "Tobias" node are returned.

Result

others
1 row
0 ms

Node[3]{name:"Andres",age:36,belt:"white"}


Try this query live. (1) {"age":25,"name":"Tobias"} (2) {"age":34,"name":"Peter"} (3) {"age":36,"belt":"white","name":"Andres"} (3)-[:KNOWS]->(1) {} (3)-[:KNOWS]->(2) {} start tobias=node(1), others=node(3, 2) where tobias<--others return others

15.11.12. Filter on patterns using NOT

The NOT() function can be used to exclude a pattern.

Query

START persons=node(*), peter=node(2)
WHERE not(persons-->peter)
RETURN persons

Nodes that do not have an outgoing relationship to the "Peter" node are returned.

Result

persons
2 rows
0 ms

Node[1]{name:"Tobias",age:25}

Node[2]{name:"Peter",age:34}


Try this query live. (1) {"age":25,"name":"Tobias"} (2) {"age":34,"name":"Peter"} (3) {"age":36,"belt":"white","name":"Andres"} (3)-[:KNOWS]->(1) {} (3)-[:KNOWS]->(2) {} start persons=node(*), peter=node(2) where not(persons-->peter) return persons

15.11.13. IN operator

To check if an element exists in a collection, you can use the IN operator.

Query

START a=node(3, 1, 2)
WHERE a.name IN ["Peter", "Tobias"]
RETURN a

This query shows how to check if a property exists in a literal collection.

Result

a
2 rows
0 ms

Node[1]{name:"Tobias",age:25}

Node[2]{name:"Peter",age:34}


Try this query live. (1) {"age":25,"name":"Tobias"} (2) {"age":34,"name":"Peter"} (3) {"age":36,"belt":"white","name":"Andres"} (3)-[:KNOWS]->(1) {} (3)-[:KNOWS]->(2) {} start a=node(3, 1, 2) where a.name IN ["Peter", "Tobias"] return a