Prev |  | Next

## 10.3. Where

`WHERE` is not a clause in it’s own right — rather, it’s part of `MATCH`, `OPTIONAL` `MATCH`, `START` and `WITH`.

In the case of `WITH` and `START`, `WHERE` simply filters the results.

For `MATCH` and `OPTIONAL` `MATCH` on the other hand, `WHERE` adds constraints to the patterns described. It should not be seen as a filter after the matching is finished.

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

Figure 10.3. Graph

### 10.3.1. Basic usage

#### Boolean operations

You can use the expected boolean operators `AND` and `OR`, and also the boolean function `NOT`. See Section 8.8, “Working with NULL” for more information on how this works with `NULL`.

Query.

    MATCH (n)
    WHERE n.name = 'Peter' XOR (n.age < 30 AND n.name = "Tobias") OR NOT (n.name = "Tobias" OR
      n.name="Peter")
    RETURN n

This query shows how boolean operators can be used.

Result

n
3 rows
`Node[0]{name:"Tobias",age:25}`
`Node[1]{name:"Peter",age:34}`
`Node[2]{name:"Andres",age:36,belt:"white"}`

#### Filter on node label

To filter nodes by label, write a label predicate after the `WHERE` keyword using `WHERE n:foo`.

Query.

    MATCH (n)
    WHERE n:Swedish
    RETURN n

The "`Andres`" node will be returned.

Result

n
1 row
`Node[2]{name:"Andres",age:36,belt:"white"}`

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

    MATCH (n)
    WHERE n.age < 30
    RETURN n

The "`Tobias`" node will be returned.

Result

n
1 row
`Node[0]{name:"Tobias",age:25}`

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

    MATCH (n)
    WHERE HAS (n.belt)
    RETURN n

The node named "`Andres`" is returned.

Result

n
1 row
`Node[2]{name:"Andres",age:36,belt:"white"}`

### 10.3.2. Regular expressions

#### Regular expressions

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

Query.

    MATCH (n)
    WHERE n.name =~ 'Tob.*'
    RETURN n

The "`Tobias`" node will be returned.

Result

n
1 row
`Node[0]{name:"Tobias",age:25}`

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

    MATCH (n)
    WHERE n.name =~ 'Some\/thing'
    RETURN n

No nodes match this regular expression.

Result

n
0 row
`(empty result)`

#### Case insensitive regular expressions

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

Query.

    MATCH (n)
    WHERE n.name =~ '(?i)ANDR.*'
    RETURN n

The node with name "`Andres`" is returned.

Result

n
1 row
`Node[2]{name:"Andres",age:36,belt:"white"}`

### 10.3.3. Using patterns in WHERE

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

    MATCH (tobias { name: 'Tobias' }),(others)
    WHERE others.name IN ['Andres', 'Peter'] AND (tobias)<--(others)
    RETURN others

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

Result

others
1 row
`Node[2]{name:"Andres",age:36,belt:"white"}`

#### Filter on patterns using NOT

The `NOT` function can be used to exclude a pattern.

Query.

    MATCH (persons),(peter { name: 'Peter' })
    WHERE NOT (persons)-->(peter)
    RETURN persons

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

Result

persons
2 rows
`Node[0]{name:"Tobias",age:25}`
`Node[1]{name:"Peter",age:34}`

#### Filter on patterns with properties

You can also add properties to your patterns:

Query.

    MATCH (n)
    WHERE (n)-[:KNOWS]-({ name:'Tobias' })
    RETURN n

Finds all nodes that have a `KNOWS` relationship to a node with the name `Tobias`.

Result

n
1 row
`Node[2]{name:"Andres",age:36,belt:"white"}`

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

    MATCH (n)-[r]->()
    WHERE n.name='Andres' AND type(r)=~ 'K.*'
    RETURN r

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

Result

r
2 rows
`:KNOWS[0]{}`
`:KNOWS[1]{}`

### 10.3.4. Collections

#### IN operator

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

Query.

    MATCH (a)
    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
`Node[0]{name:"Tobias",age:25}`
`Node[1]{name:"Peter",age:34}`

### 10.3.5. Missing properties and values

#### Default to false if property is missing

As missing properties evaluate to `NULL`, the comparision in the example will evaluate to `FALSE` for nodes without the `belt` property.

Query.

    MATCH (n)
    WHERE n.belt = 'white'
    RETURN n

Only nodes with the belt property are returned.

Result

n
1 row
`Node[2]{name:"Andres",age:36,belt:"white"}`

#### Default to true if property is missing

If you want to compare a property on a graph element, but only if it exists, you can compare the property against both the value you are looking for and `NULL`, like:

Query.

    MATCH (n)
    WHERE n.belt = 'white' OR n.belt IS NULL RETURN n
    ORDER BY n.name

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

Result

n
3 rows
`Node[2]{name:"Andres",age:36,belt:"white"}`
`Node[1]{name:"Peter",age:34}`
`Node[0]{name:"Tobias",age:25}`

#### Filter on NULL

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.

    MATCH (person)
    WHERE person.name = 'Peter' AND person.belt IS NULL RETURN person

Nodes that Tobias is not connected to are returned.

Result

person
1 row
`Node[1]{name:"Peter",age:34}`

Copyright © 2014 Neo Technology

Prev | Up | Next
| Home |