# Expressions

This section contains an overview of expressions in Cypher with examples.

## Expressions in general

 Most expressions in Cypher evaluate to `null` if any of their inner expressions are `null`. Notable exceptions are the operators `IS NULL` and `IS NOT NULL`.

An expression in Cypher can be:

• A decimal (integer or float) literal: `13`, `-40000`, `3.14`.

• A decimal (integer or float) literal in scientific notation: `6.022E23`.

• A hexadecimal integer literal (starting with `0x`): `0x13af`, `0xFC3A9`, `-0x66eff`.

• An octal integer literal (starting with `0o`): `0o1372`, `-0o5671`.

• A string literal: `'Hello'`, `"World"`.

• A float literal: `Inf`, `Infinity`, `NaN`

• A boolean literal: `true`, `false`.

• A variable: `n`, `x`, `rel`, `myFancyVariable`, ``A name with weird stuff in it[]!``.

• A property: `n.prop`, `x.prop`, `rel.thisProperty`, `myFancyVariable.`(weird property name)``.

• A dynamic property: `n["prop"]`, `rel[n.city + n.zip]`, `map[coll[0]]`.

• A parameter: `\$param`, `\$0`.

• A list of expressions: `['a', 'b']`, `[1, 2, 3]`, `['a', 2, n.property, \$param]`, `[]`.

• A function call: `length(p)`, `nodes(p)`.

• An aggregate function: `avg(x.prop)`, `count(*)`.

• A path-pattern: `(a)-[r]->(b)`, `(a)-[r]-(b)`, `(a)--(b)`, `(a)-->()<--(b)`.

• An operator application: `1 + 2`, `3 < 4`.

• A predicate expression is an expression that returns `true` or `false`: `a.prop = 'Hello'`, `length(p) > 10`, `a.name IS NOT NULL`.

• A special case of predicates are label and relationship type expressions: `(n:A|B)`, `()-[r:R1|R2]→()`.

• A subquery expression. For example: ```EXISTS { MATCH (n)-[r]→(p) WHERE p.name = 'Sven' }```.

• A regular expression: `a.name =~ 'Tim.*'`.

• A case-sensitive string matching expression: `a.surname STARTS WITH 'Sven'`, `a.surname ENDS WITH 'son'` or `a.surname CONTAINS 'son'`.

• A `CASE` expression.

## Note on string literals

String literals can contain the following escape sequences:

Escape sequence Character

`\t`

Tab

`\b`

Backspace

`\n`

Newline

`\r`

Carriage return

`\f`

Form feed

`\'`

Single quote

`\"`

Double quote

`\\`

Backslash

`\uxxxx`

Unicode UTF-16 code point (4 hex digits must follow the `\u`)

 Using regular expressions with unsanitized user input makes you vulnerable to Cypher injection. Consider using parameters instead.

## Note on number literals

Any number literal may contain an underscore `_` between digits. There may be an underscore between the `0x` or `0o` and the digits for hexadecimal and octal literals.

## `CASE` expressions

Generic conditional expressions may be expressed using the `CASE` construct. Two variants of `CASE` exist within Cypher: the simple form, which allows an expression to be compared against multiple values, and the generic form, which allows multiple conditional statements to be expressed.

 CASE can only be used as part of RETURN or WITH if you want to use the result in the succeeding clause or statement.

The following graph is used for the examples below:

### Simple `CASE` form: comparing an expression against multiple values

The expression is calculated, and compared in order with the `WHEN` clauses until a match is found. If no match is found, the expression in the `ELSE` clause is returned. However, if there is no `ELSE` case and no match is found, `null` will be returned.

``````CASE test
WHEN value THEN result
[WHEN ...]
[ELSE default]
END``````

Arguments:

Name Description

`test`

A valid expression.

`value`

An expression whose result will be compared to `test`.

`result`

This is the expression returned as output if `value` matches `test`.

`default`

If no match is found, `default` is returned.

Query
``````MATCH (n)
RETURN
CASE n.eyes
WHEN 'blue'  THEN 1
WHEN 'brown' THEN 2
ELSE 3
END AS result``````
Table 1. Result
result

`2`

`1`

`3`

`2`

`1`

Rows: 5

### Generic `CASE` form: allowing for multiple conditionals to be expressed

The predicates are evaluated in order until a `true` value is found, and the result value is used. If no match is found, the expression in the `ELSE` clause is returned. However, if there is no `ELSE` case and no match is found, `null` will be returned.

``````CASE
WHEN predicate THEN result
[WHEN ...]
[ELSE default]
END``````

Arguments:

Name Description

`predicate`

A predicate that is tested to find a valid alternative.

`result`

This is the expression returned as output if `predicate` evaluates to `true`.

`default`

If no match is found, `default` is returned.

Query
``````MATCH (n)
RETURN
CASE
WHEN n.eyes = 'blue' THEN 1
WHEN n.age < 40      THEN 2
ELSE 3
END AS result``````
Table 2. Result
result

`2`

`1`

`3`

`3`

`1`

Rows: 5

### Distinguishing between when to use the simple and generic `CASE` forms

Owing to the close similarity between the syntax of the two forms, sometimes it may not be clear at the outset as to which form to use. We illustrate this scenario by means of the following query, in which there is an expectation that `age_10_years_ago` is `-1` if `n.age` is `null`:

Query
``````MATCH (n)
RETURN n.name,
CASE n.age
WHEN n.age IS NULL THEN -1
ELSE n.age - 10
END AS age_10_years_ago``````

However, as this query is written using the simple `CASE` form, instead of `age_10_years_ago` being `-1` for the node named `Daniel`, it is `null`. This is because a comparison is made between `n.age` and `n.age IS NULL`. As `n.age IS NULL` is a boolean value, and `n.age` is an integer value, the `WHEN n.age IS NULL THEN -1` branch is never taken. This results in the `ELSE n.age - 10` branch being taken instead, returning `null`.

Table 3. Result
n.name age_10_years_ago

`"Alice"`

`28`

`"Bob"`

`15`

`"Charlie"`

`43`

`"Daniel"`

`<null>`

`"Eskil"`

`31`

Rows: 5

The corrected query, behaving as expected, is given by the following generic `CASE` form:

Query
``````MATCH (n)
RETURN n.name,
CASE
WHEN n.age IS NULL THEN -1
ELSE n.age - 10
END AS age_10_years_ago``````

We now see that the `age_10_years_ago` correctly returns `-1` for the node named `Daniel`.

Table 4. Result
n.name age_10_years_ago

`"Alice"`

`28`

`"Bob"`

`15`

`"Charlie"`

`43`

`"Daniel"`

`-1`

`"Eskil"`

`31`

Rows: 5

### Using the result of `CASE` in the succeeding clause or statement

You can use the result of `CASE` to set properties on a node or relationship. For example, instead of specifying the node directly, you can set a property for a node selected by an expression:

Query
``````MATCH (n)
WITH n,
CASE n.eyes
WHEN 'blue'  THEN 1
WHEN 'brown' THEN 2
ELSE 3
END AS colourCode
SET n.colourCode = colourCode``````

For more information about using the `SET` clause, see SET.

 `(empty result)` Rows: 0 Properties set: 5

### Using `CASE` with null values

When using the simple `CASE` form, it is useful to remember that in Cypher `null = null` yields `null`.

Example 1. CASE

For example, you might expect `age_10_years_ago` to be `-1` for the node named `Daniel`:

Query
``````MATCH (n)
RETURN n.name,
CASE n.age
WHEN null THEN -1
ELSE n.age - 10
END AS age_10_years_ago``````

However, as `null = null` does not yield `true`, the `WHEN null THEN -1` branch is never taken, resulting in the `ELSE n.age - 10` branch being taken instead, returning `null`.

Table 6. Result
n.name age_10_years_ago

`"Alice"`

`28`

`"Bob"`

`15`

`"Charlie"`

`43`

`"Daniel"`

`<null>`

`"Eskil"`

`31`

Rows: 5

## Subquery expressions

Subquery expressions can appear anywhere that an expression is valid. A subquery has a scope, as indicated by the opening and closing braces, `{` and `}`. Any variable that is defined in the outside scope can be referenced inside the subquery’s own scope. Variables introduced inside the subquery are not part of the outside scope and therefore can’t be accessed on the outside.

The following graph is used for the examples below:

### `EXISTS` subqueries

An `EXISTS` subquery can be used to find out if a specified pattern exists at least once in the data. It serves the same purpose as a path pattern but is more powerful because it allows you to use `MATCH` and `WHERE` clauses internally. Moreover, it can appear in any expression position, unlike path patterns. If the subquery evaluates to at least one row, the whole expression will become `true`. This also means that the system only needs to evaluate if there is at least one row and can skip the rest of the work.

Any non-writing query is allowed. `EXISTS` subqueries differ from regular queries in that the final `RETURN` clause may be omitted, as any variable defined within the subquery will not be available outside of the expression, even if a final `RETURN` clause is used.

It is worth noting that the `MATCH` keyword can be omitted in subqueries in cases where the `EXISTS` consists of only a pattern and an optional `WHERE` clause.

#### Simple `EXISTS` subquery

Variables introduced by the outside scope can be used in the `EXISTS` subquery without importing them. In this regard, `EXISTS` subqueries are different from `CALL` subqueries, which do require importing. The following example shows this:

Query
``````MATCH (person:Person)
WHERE EXISTS {
(person)-[:HAS_DOG]->(:Dog)
}
RETURN person.name AS name``````
Table 7. Result
name

`"Andy"`

`"Peter"`

Rows: 2

#### `EXISTS` subquery with `WHERE` clause

A `WHERE` clause can be used in conjunction to the `MATCH`. Variables introduced by the `MATCH` clause and the outside scope can be used in this scope.

Query
``````MATCH (person:Person)
WHERE EXISTS {
MATCH (person)-[:HAS_DOG]->(dog:Dog)
WHERE person.name = dog.name
}
RETURN person.name AS name``````
Table 8. Result
name

`"Andy"`

Rows: 1

#### Nesting `EXISTS` subqueries

`EXISTS` subqueries can be nested like the following example shows. The nesting also affects the scopes. That means that it is possible to access all variables from inside the subquery which are either from the outside scope or defined in the very same subquery.

Query
``````MATCH (person:Person)
WHERE EXISTS {
MATCH (person)-[:HAS_DOG]->(dog:Dog)
WHERE EXISTS {
MATCH (dog)-[:HAS_TOY]->(toy:Toy)
WHERE toy.name = 'Banana'
}
}
RETURN person.name AS name``````
Table 9. Result
name

`"Peter"`

Rows: 1

#### `EXISTS` subquery outside of a `WHERE` clause

`EXISTS` subquery expressions can appear anywhere that an expression is valid. Here the result is a boolean that shows whether the subquery can find the given pattern.

Query
``````MATCH (person:Person)
RETURN person.name AS name, EXISTS {
MATCH (person)-[:HAS_DOG]->(:Dog)
} AS hasDog``````
Table 10. Result
name hasDog

`"Andy"`

`true`

`"Timothy"`

`false`

`"Peter"`

`true`

Rows: 3

#### `EXISTS` subquery with a `UNION`

`Exists` can be used with a `UNION` clause, and the `RETURN` clauses are not required. It is worth noting that if one branch has a `RETURN` clause, then all branches require one. The below example demonstrates that if one of the `UNION` branches was to return at least one row, the entire `EXISTS` expression will evaluate to true.

Query
``````MATCH (person:Person)
RETURN
person.name AS name,
EXISTS {
MATCH (person)-[:HAS_DOG]->(:Dog)
UNION
MATCH (person)-[:HAS_CAT]->(:Cat)
} AS hasPet``````
Table 11. Result
name hasPet

`"Andy"`

`true`

`"Timothy"`

`true`

`"Peter"`

`true`

Rows: 3

#### `EXISTS` subquery with `WITH`

Variables from the outside scope are visible for the entire subquery, even when using a `WITH` clause. This means that shadowing of these variables is not allowed. An outside scope variable is shadowed when a newly introduced variable within the inner scope is defined with the same variable. In the below example, a `WITH` clause introduces a new variable. Note that the outer scope variable `person` referenced in the main query is still available after the `WITH` clause.

Query
``````MATCH (person:Person)
WHERE EXISTS {
WITH "Ozzy" AS dogName
MATCH (person)-[:HAS_DOG]->(d:Dog)
WHERE d.name = dogName
}
RETURN person.name AS name``````
Table 12. Result
name

`"Peter"`

Rows: 1

#### `EXISTS` subquery with `RETURN`

`EXISTS` subqueries do not require a `RETURN` clause at the end of the subquery. If one is present, it does not need to be aliased, which is different compared to `CALL` subqueries. Any variables returned in an `EXISTS` subquery will not be available after the subquery.

Query
``````MATCH (person:Person)
WHERE EXISTS {
MATCH (person)-[:HAS_DOG]->(:Dog)
RETURN person.name
}
RETURN person.name AS name``````
Table 13. Result
name

`"Andy"`

`"Peter"`

Rows: 2

### `COUNT` subqueries

A `COUNT` subquery expression can be used to count the number of rows returned by the subquery.

Any non-writing query is allowed. `COUNT` subqueries differ from regular queries in that the final `RETURN` clause may be omitted, as any variable defined within the subquery will not be available outside of the expression, even if a final `RETURN` clause is used. One exception to this is that for a `DISTINCT UNION` clause, the `RETURN` clause is still mandatory.

It is worth noting that the `MATCH` keyword can be omitted in subqueries in cases where the `COUNT` consists of only a pattern and an optional `WHERE` clause.

#### Simple `COUNT` subquery

Variables introduced by the outside scope can be used in the `COUNT` subquery without importing them. In this regard, `COUNT` subqueries are different from `CALL` subqueries, which do require importing. The following query exemplifies this and outputs the owners of more than one dog:

Query
``````MATCH (person:Person)
WHERE COUNT { (person)-[:HAS_DOG]->(:Dog) } > 1
RETURN person.name AS name``````
Table 14. Result
name

`"Peter"`

Rows: 1

#### `COUNT` subquery with `WHERE` clause

A `WHERE` clause can be used inside the `COUNT` pattern. Variables introduced by the `MATCH` clause and the outside scope can be used in this scope.

Query
``````MATCH (person:Person)
WHERE COUNT {
(person)-[:HAS_DOG]->(dog:Dog)
WHERE person.name = dog.name
} = 1
RETURN person.name AS name``````
Table 15. Result
name

`"Andy"`

Rows: 1

#### `COUNT` subquery with a `UNION`

`COUNT` can be used with a `UNION` clause. If the `UNION` clause is distinct, the `RETURN` clause is required. `UNION ALL` clauses do not require the `RETURN` clause. However, it is worth noting that if one branch has a `RETURN` clause, then all require one. The below example shows the count of pets each person has by using a `UNION` clause:

Query
``````MATCH (person:Person)
RETURN
person.name AS name,
COUNT {
MATCH (person)-[:HAS_DOG]->(dog:Dog)
RETURN dog.name AS petName
UNION
MATCH (person)-[:HAS_CAT]->(cat:Cat)
RETURN cat.name AS petName
} AS numPets``````
Table 16. Result
name numPets

`"Andy"`

`1`

`"Timothy"`

`1`

`"Peter"`

`2`

Rows: 3

#### `COUNT` subquery with `WITH`

Variables from the outside scope are visible for the entire subquery, even when using a `WITH` clause. This means that shadowing of these variables is not allowed. An outside scope variable is shadowed when a newly introduced variable within the inner scope is defined with the same variable. In the below example, a `WITH` clause introduces a new variable. Note that the outer scope variable `person` referenced in the main query is still available after the `WITH` clause.

Query
``````MATCH (person:Person)
WHERE COUNT {
WITH "Ozzy" AS dogName
MATCH (person)-[:HAS_DOG]->(d:Dog)
WHERE d.name = dogName
} = 1
RETURN person.name AS name``````
Table 17. Result
name

`"Peter"`

Rows: 1

#### Using `COUNT` subqueries inside other clauses

`COUNT` can be used in any position in a query, with the exception of administration commands, where it is restricted. See a few examples below:

##### Using `COUNT` in `RETURN`
Query
``````MATCH (person:Person)
RETURN person.name, COUNT { (person)-[:HAS_DOG]->(:Dog) } as howManyDogs``````
Table 18. Result
person.name howManyDogs

`"Andy"`

`1`

`"Timothy"`

`0`

`"Peter"`

`2`

Rows: 3

##### Using `COUNT` in `SET`
Query
``````MATCH (person:Person) WHERE person.name ="Andy"
SET person.howManyDogs = COUNT { (person)-[:HAS_DOG]->(:Dog) }
RETURN person.howManyDogs as howManyDogs``````
Table 19. Result
howManyDogs

`1`

Rows: 1
Properties set: 1

##### Using `COUNT` in `CASE`
Query
``````MATCH (person:Person)
RETURN
CASE
WHEN COUNT { (person)-[:HAS_DOG]->(:Dog) } > 1 THEN "Doglover " + person.name
ELSE person.name
END AS result``````
Table 20. Result
result

`"Andy"`

`"Timothy"`

`"Doglover Peter"`

Rows: 3

##### Using `COUNT` as a grouping key

The following query groups all persons by how many dogs they own, and then calculates the average age for each group.

Query
``````MATCH (person:Person)
RETURN COUNT { (person)-[:HAS_DOG]->(:Dog) } AS numDogs,
avg(person.age) AS averageAge
ORDER BY numDogs``````
Table 21. Result
numDogs averageAge

`0`

`25.0`

`1`

`36.0`

`2`

`35.0`

Rows: 3

#### `COUNT` subquery with `RETURN`

`COUNT` subqueries do not require a `RETURN` clause at the end of the subquery. If one is present, it does not need to be aliased. This is a difference compared to from `CALL` subqueries. Any variables returned in a `COUNT` subquery will not be available after the subquery.

Query
``````MATCH (person:Person)
WHERE COUNT {
MATCH (person)-[:HAS_DOG]->(:Dog)
RETURN person.name
} = 1
RETURN person.name AS name``````
Table 22. Result
name

`"Andy"`

Rows: 1

### `COLLECT` subqueries

A `COLLECT` subquery expression can be used to create a list with the rows returned by a given subquery.

Any non-writing query is allowed. `COLLECT` subqueries differ from `COUNT` and `EXISTS` subqueries in that the final `RETURN` clause is mandatory. The `RETURN` clause must return exactly one column.

#### Simple `COLLECT` subquery

Variables introduced by the outside scope can be used in the `COLLECT` subquery without importing them. In this regard, `COLLECT` subqueries are different from `CALL` subqueries, which do require importing. The following query exemplifies this and outputs the owners of the dog named `Ozzy`:

Query
``````MATCH (person:Person)
WHERE 'Ozzy' IN COLLECT { MATCH (person)-[:HAS_DOG]->(dog:Dog) RETURN dog.name }
RETURN person.name AS name``````
Table 23. Result
name

`"Peter"`

Rows: 1

#### `COLLECT` subquery with `WHERE` clause

A `WHERE` clause can be used inside the `COLLECT` pattern. Variables introduced by the `MATCH` clause and the outside scope can be used in the inner scope.

Query
``````MATCH (person:Person)
RETURN person.name as name, COLLECT {
MATCH (person)-[r:HAS_DOG]->(dog:Dog)
WHERE r.since > 2017
RETURN dog.name
} as youngDogs``````
Table 24. Result
name youngDogs

`"Andy"`

`[]`

`"Timothy"`

`[]`

`"Peter"`

`["Ozzy"]`

Rows: 3

#### `COLLECT` subquery with a `UNION`

`COLLECT` can be used with a `UNION` clause. The below example shows the collection of pet names each person has by using a `UNION` clause:

Query
``````MATCH (person:Person)
RETURN
person.name AS name,
COLLECT {
MATCH (person)-[:HAS_DOG]->(dog:Dog)
RETURN dog.name AS petName
UNION
MATCH (person)-[:HAS_CAT]->(cat:Cat)
RETURN cat.name AS petName
} AS petNames``````
Table 25. Result
name petNames

`"Andy"`

`["Andy"]`

`"Timothy"`

`["Mittens"]`

`"Peter"`

`["Ozzy", "Fido"]`

Rows: 3

#### `COLLECT` subquery with `WITH`

Variables from the outside scope are visible for the entire subquery, even when using a `WITH` clause. This means that shadowing of these variables is not allowed. An outside scope variable is shadowed when a newly introduced variable within the inner scope is defined with the same variable. In the below example, the outer variable `name` is shadowed and will therefore throw an error.

Query
``````WITH 'Peter' as name
MATCH (person:Person {name: name})
RETURN COLLECT {
WITH 'Ozzy' AS name
MATCH (person)-[r:HAS_DOG]->(d:Dog {name: name})
RETURN d.name
} as dogsOfTheYear``````
Error message
``The variable `name` is shadowing a variable with the same name from the outer scope and needs to be renamed (line 4, column 20 (offset: 92))``

New variables can be introduced into the subquery, as long as they use a different identifier. In the below example, a `WITH` clause introduces a new variable. Note that the outer scope variable `person` referenced in the main query is still available after the `WITH` clause.

Query
``````MATCH (person:Person)
RETURN person.name AS name, COLLECT {
WITH 2018 AS yearOfTheDog
MATCH (person)-[r:HAS_DOG]->(d:Dog)
WHERE r.since = yearOfTheDog
RETURN d.name
} as dogsOfTheYear``````
Table 26. Result
name dogsOfTheYear

`"Andy"`

`[]`

`"Timothy"`

`[]`

`"Peter"`

`["Ozzy"]`

Rows: 3

#### Using `COLLECT` subqueries inside other clauses

`COLLECT` can be used in any position in a query, with the exception of administration commands, where the `COLLECT` expression is restricted. See a few examples below of how `COLLECT` can be used in different positions within a query:

##### Using `COLLECT` in `RETURN`
Query
``````MATCH (person:Person)
RETURN person.name,
COLLECT {
MATCH (person)-[:HAS_DOG]->(d:Dog)
MATCH (d)-[:HAS_TOY]->(t:Toy)
RETURN t.name
} as toyNames``````
Table 27. Result
person.name toyNames

`"Andy"`

`[]`

`"Timothy"`

`[]`

`"Peter"`

`["Banana"]`

Rows: 3

##### Using `COLLECT` in `SET`
Query
``````MATCH (person:Person) WHERE person.name = "Peter"
SET person.dogNames = COLLECT { MATCH (person)-[:HAS_DOG]->(d:Dog) RETURN d.name }
RETURN person.dogNames as dogNames``````
Table 28. Result
dogNames

`["Ozzy", "Fido"]`

Rows: 1
Properties set: 1

##### Using `COLLECT` in `CASE`
Query
``````MATCH (person:Person)
RETURN
CASE
WHEN COLLECT { MATCH (person)-[:HAS_DOG]->(d:Dog) RETURN d.name } = []  THEN "No Dogs " + person.name
ELSE person.name
END AS result``````
Table 29. Result
result

`"Andy"`

`"No Dogs Timothy"`

`"Peter"`

Rows: 3

##### Using `COLLECT` as a grouping key

The following query collects all persons by their dogs' names, and then calculates the average age for each group.

Query
``````MATCH (person:Person)
RETURN COLLECT { MATCH (person)-[:HAS_DOG]->(d:Dog) RETURN d.name } AS dogNames,
avg(person.age) AS averageAge
ORDER BY dogNames``````
Table 30. Result
dogNames averageAge

`[]`

`25.0`

`["Andy"]`

`36.0`

`["Ozzy", "Fido"]`

`35.0`

Rows: 3

##### Using `COLLECT` vs `collect()`

`COLLECT` does not handle `null` values in the same way that function `collect()` does. The `collect()` function automatically removes `null` values. `COLLECT` will not remove `null` values automatically. However, they can be removed by adding a filtering step in the subquery.

The following queries illustrate these differences:

Query
``````MATCH (p:Person)
RETURN collect(p.nickname) AS names``````
Table 31. Result
names

`["Pete", "Tim"]`

Rows: 1

Query
``````RETURN COLLECT {
MATCH (p:Person)
RETURN p.nickname ORDER BY p.nickname
} AS names``````
Table 32. Result
names

`["Pete", "Tim", null]`

Rows: 1

Query
``````RETURN COLLECT {
MATCH (p:Person)
WHERE p.nickname IS NOT NULL
RETURN p.nickname ORDER BY p.nickname
} AS names``````
Table 33. Result
name

`["Pete", "Tim"]`

Rows: 1

## Label expressions

In earlier versions of Neo4j, label expressions for nodes had a single colon operator that represented the `AND` operator. With the release of version 5, a new label expression with an extended set of logical operators is being introduced, in addition to the single colon operator. It is important to note that you cannot mix these different types of label expression syntax. For more information, see Restrictions on using the different types of label expression syntax.

Label expressions evaluate to `true` or `false` when applied to the set of labels for a node.

Assuming no other filters are applied, then a label expression evaluating to `true` means the node is matched.

The following table displays whether the label expression matches the relationship:

 Node Label expression `()` `(:A)` `(:B)` `(:C)` `(:A:B)` `(:A:C)` `(:B:C)` `(:A:B:C)` `()` `(:A)` `(:A&B)` `(:A|B)` `(:!A)` `(:!!A)` `(:A&!A)` `(:A|!A)` `(:%)` `(:!%)` `(:%|!%)` `(:%&!%)` `(:A&%)` `(:A|%)` `(:(A&B)&!(B&C))` `(:!(A&%)&%)`

### Restrictions on using the different types of label expression syntax

Neo4j version 5 introduces an ampersand operator, which is equivalent to the colon conjunction operator. Mixing the colon conjunction operator with any of the new label expression operators in the same clause will raise a syntax error.

For example, each of the following clauses will raise syntax errors:

• `MATCH (n:A|B:C)`

• `MATCH (n:A:B)-[]-(m:(A&B)|C)`

• `MATCH (n:A:B)--(m), (n)-→(o:(A&B)|C)`

• `RETURN n:A&B, n:A:B`

• `MATCH (n:A:B)-[]-(m) WHERE m:(A&B)|C`

In earlier versions of Neo4j (version 4.4 and earlier), relationship type expressions only had the pipe operator. As the pipe operator will continue to act as an `OR` operator, it can continue to be used alongside the new operators.

To make it easier to use the new syntax when extending existing queries, using the different syntax types in separate clauses will be supported.

For example, the following query will not raise a syntax error:

``````MATCH (m:A:B:C)-[]->()
MATCH (n:(A&B)|C)-[]->(m)
RETURN m,n``````

Queries that exclusively use syntax from earlier versions of Neo4j (version 4.4 and earlier) will continue to be supported.

For example, the following will not raise a syntax error:

``````MATCH (m:A:B:C)-[:S|T]->()
RETURN
CASE
WHEN m:D:E THEN m.p
ELSE null
END AS result``````

#### Examples

The following graph is used for the examples below:

### Node pattern without label expressions

A node pattern without a label expression returns all nodes in the graph, including nodes without labels.

Example 2. Label expression
Query
``````MATCH (n)
RETURN n.name AS name``````
Table 35. Result
name

`"Alice"`

`"Bob"`

`"Charlie"`

`"Daniel"`

`"Eskil"`

`"Frank"`

`"George"`

`"Henry"`

Rows: 8

### Node pattern with a single node label

A node pattern with a single label returns the nodes that contain the specified label.

Example 3. Label expression
Query
``````MATCH (n:A)
RETURN n.name AS name``````
Table 36. Result
name

`"Alice"`

`"Daniel"`

`"Eskil"`

`"George"`

Rows: 4

### Node pattern with an `AND` expression for the node labels

A node pattern with an `AND` expression for the node label returns the nodes that contain both of the specified labels.

Example 4. Label expression
Query
``````MATCH (n:A&B)
RETURN n.name AS name``````
Table 37. Result
name

`"Daniel"`

`"George"`

Rows: 2

### Node pattern with an `OR` expression for the node labels

A match with `OR` expressions for the node label returns the nodes that contain either of the specified labels.

Example 5. Label expression
Query
``````MATCH (n:A|B)
RETURN n.name AS name``````
Table 38. Result
name

`"Alice"`

`"Bob"`

`"Daniel"`

`"Eskil"`

`"Frank"`

`"George"`

Rows: 6

### Node pattern with `NOT` expressions for the node labels

A node pattern with a `NOT` expression for the node label returns the nodes that do not contain the specified label.

Example 6. Label expression
Query
``````MATCH (n:!A)
RETURN n.name AS name``````
Table 39. Result
name

`"Bob"`

`"Charlie"`

`"Frank"`

`"Henry"`

Rows: 4

### Node pattern with a `Wildcard` expression for the node labels

A node pattern with a `Wildcard` expression for the node label returns all the nodes that contain at least one label.

Example 7. Label expression
Query
``````MATCH (n:%)
RETURN n.name AS name``````
Table 40. Result
name

`"Alice"`

`"Bob"`

`"Charlie"`

`"Daniel"`

`"Eskil"`

`"Frank"`

`"George"`

Rows: 7

### Node pattern with nested label expressions

A node pattern with nested label expressions returns the nodes for which the full expression is `true`.

Example 8. Label expression
Query
``````MATCH (n:(!A&!B)|C)
RETURN n.name AS name``````
Table 41. Result
name

`"Charlie"`

`"Eskil"`

`"Frank"`

`"George"`

`"Henry"`

Rows: 5

### `WHERE` clause with label expressions as a predicate

A label expression can also be used as a predicate in the `WHERE` clause.

Example 9. Label expression
Query
``````MATCH (n)
WHERE n:A|B
RETURN n.name AS name``````
Table 42. Result
name

`"Alice"`

`"Bob"`

`"Daniel"`

`"Eskil"`

`"Frank"`

`"George"`

Rows: 6

### Label expressions in the `WITH` and `RETURN` clauses

A label expression can also be used in a `WITH` or a `RETURN` clause.

Example 10. Label expression
Query
``````MATCH (n)
RETURN n:A&B``````
Table 43. Result
n:A&B

`false`

`false`

`false`

`true`

`false`

`false`

`true`

`false`

Rows: 8

## Relationship type expressions

Relationship type expressions evaluate to `true` or `false` when applied to the type of a relationship.

Assuming no other filters are applied, then a relationship type expression evaluating to `true` means the relationship is matched.

 Relationships must have exactly one type. So for example the expressions: `(a)-[r:R&Q]-(b)` or `(a)-[r:!%]-(b)` will never return any results.
 Variable length relationships may only have relationship type expressions consisting of `|`. That means that `()-[r:!R*]-()` is not allowed, whereas `()-[r:Q|R*]-()` is allowed.
 Relationships must have exactly one type. For example `(a)-[r:R&Q]-(b)` or `(a)-[r:!%]-(b)` will never return any results.

The following table displays whether the relationship type expression matches the relationship:

 Relationship Relationship type expression `[:A]` `[:B]` `[:C]` `[]` `[:A]` `[:A&B]` `[:A|B]` `[:!A]` `[:!!A]` `[:A&!A]` `[:A|!A]` `[:%]` `[:!%]` `[:%|!%]` `[:%&!%]` `[:A&%]` `[:A|%]`

Label expressions cannot be combined with label syntax. For example, `:A:B&C` will throw an error. Instead, use either `:A&B&C` or `:A:B:C`.

Examples:

The following graph is used for the examples below:

### Relationship pattern without relationship type expression

A relationship pattern without a relationship type expression returns all relationships in the graph.

Example 11. Relationship type expressions
Query
``````MATCH ()-[r]->()
RETURN r.name as name``````
Table 44. Result
name

`"Teaches"`

`"Studies"`

`"Parents"`

Rows: 3

### Relationship pattern with a single relationship type

A relationship pattern with a single relationship type returns the relationships that contain the specified type.

Example 12. Relationship type expression
Query
``````MATCH ()-[r:R1]->()
RETURN r.name AS name``````
Table 45. Result
name

`"Teaches"`

Rows: 1

### Relationship pattern with an `OR` expression for the relationship types

A relationship pattern with an `OR` expression for the relationship type returns all relationships that contain either of the specified types.

Example 13. Relationship type expression
Query
``````MATCH ()-[r:R1|R2]->()
RETURN r.name AS name``````
Table 46. Result
name

`"Teaches"`

`"Studies"`

Rows: 2

### Relationship pattern with a `NOT` expression for the relationship types

A relationship pattern with a `NOT` expression for the relationship type returns all relationships that do not contain the specified type.

Example 14. Relationship type expression
Query
``````MATCH ()-[r:!R1]->()
RETURN r.name AS name``````
Table 47. Result
name

`"Studies"`

`"Parents"`

Rows: 2

### Relationship pattern with a nested relationship type expression

A relationship pattern with a nested relationship type expression returns all relationships for which the full expression is `true`.

Example 15. Relationship type expression
Query
``````MATCH ()-[r:(!R1&!R2)|R3]->()
RETURN r.name as name``````
Table 48. Result
name

`"Parents"`

Rows: 1

### `WHERE` clause with a relationship type expression in the predicate

A relationship type expression can also be used as a predicate in the `WHERE` clause.

Example 16. Relationship type expression
Query
``````MATCH (n)-[r]->(m)
WHERE r:R1|R2
RETURN r.name AS name``````
Table 49. Result
name

`"Teaches"`

`"Studies"`

Rows: 2

### `WITH` and `RETURN` clauses with a relationship type expression

A relationship type expression can also be used in the `WITH` or `RETURN` clauses.

Example 17. Relationship type expression
Query
``````MATCH (n)-[r]->(m)
RETURN r:R1|R2 AS result``````
Table 50. Result
result

`true`

`true`

`false`

Rows: 3

### `CASE` expression with relationship type and label expressions

A relationship type expression and a label expression can also be used in `CASE` expressions.

Example 18. Relationship type expression
Query
``````MATCH (n)-[r]->(m)
RETURN
CASE
WHEN n:A&B THEN 1
WHEN r:!R1&!R2 THEN 2
ELSE -1
END AS result``````
Table 51. Result
result

`1`

`-1`

`2`

Rows: 3