Label expression predicates

You can use a label expression predicate to verify that the labels of a node or the relationship type of a relationship match a given label expression.

Cypher® supports two label expression alternatives:

  • Colon form (<expr>:<label-expression>)

  • IS [NOT] LABELED form Introduced in Neo4j 2026.04 Cypher 25 only

Syntax

Colon form

<expr>:<label-expression>

Where <expr> is any Cypher expression and <label-expression> is any Cypher label expression.

IS [NOT] LABELED predicate

<expr> IS LABELED <label-expression>
<expr> IS NOT LABELED <label-expression>
<expr> IS NOT <label-expression>
  • If <expr> evaluates to null, the predicate result is null.

  • Otherwise, the label expression is evaluated against the node’s label set or the relationship’s single type, and the result is true or false equivalent to the colon form.

  • IS NOT LABELED <label-expression> negates the result of the entire label expression. This is different from using ! inside the label expression. For example:

    • n IS LABELED !A&B means the node has label B, and does not have label A.

    • n IS NOT LABELED A&B means the node does not have both label A and label B.

IS [NOT] LABELED is only valid in expression contexts, (for example, WHERE, RETURN, WITH, on the right-hand side of SET property assignments, or in CASE branches). It cannot be used in place of a label expression inside a node pattern or relationship pattern (for example MATCH (n IS LABELED Person) is invalid), nor as SET / REMOVE label specification syntax. In patterns and when attaching or removing labels, use the colon form instead (for example (n:Person)).

Example graph

The following graph is used for the examples on this page:

label expression predicates graph

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

CREATE (alice:Person&Manager {name:'Alice', age: 65, skills: ['Java', 'Python']}),
       (cecil:Person&Developer {name: 'Cecil', age: 25, skills: ['Java', 'Python']}),
       (cecilia:Person&Developer {name: 'Cecilia', age: 31, skills: ['JavaScript', 'TypeScript']}),
       (charlie:Person&Engineer {name: 'Charlie', age: 61, skills: ['C++', 'Python']}),
       (daniel:Person&Director {name: 'Daniel', age: 39, skills: ['JavaScript', 'Slides']}),
       (eskil:Person&CEO {name: 'Eskil', age: 39, skills: ['Slides', 'ChatGPT']}),

       (cecil)-[:WORKS_FOR]->(alice),
       (cecilia)-[:WORKS_FOR]->(alice),
       (charlie)-[:WORKS_FOR]->(daniel),
       (alice)-[:REPORTS_TO]->(daniel),
       (daniel)-[:REPORTS_TO]->(eskil)

Test whether a node has a certain label

Given that p is a node, p:Manager tests whether p has the label Manager or not and results in true or false, respectively.

MATCH (p:Person)
RETURN p.name AS name, p:Manager AS isManager
name isManager

"Alice"

true

"Cecil"

false

"Cecilia"

false

"Charlie"

false

"Daniel"

false

"Eskil"

false

Rows: 6

Given that p is a node and a more complex label expression, e.g, Manager|Director|CEO, p:Manager|Director|CEO tests whether node p matches the label expression Manager|Director|CEO or not and results in true or false, respectively. More specifically, p:Manager|Director|CEO tests whether p has at least one of the three labels Manager, Director, and CEO.

MATCH (p:Person)
RETURN p.name AS name,
       p:Manager|Director|CEO AS isManager
name isManager

"Alice"

true

"Cecil"

false

"Cecilia"

false

"Charlie"

false

"Daniel"

true

"Eskil"

true

Rows: 6

p:!CEO tests whether p does not have the label CEO.

MATCH (p:Person)-[r]->(m)
RETURN p.name AS name,
       m:!CEO AS doesNotWorkDirectlyForTheCEO
name doesNotWorkDirectlyForTheCEO

"Alice"

true

"Cecil"

true

"Cecilia"

true

"Charlie"

true

"Daniel"

false

Rows: 5

When <expr> evaluates to null, the label expression predicate results in null; for example if p is null, then p:!CEO results in null.

MATCH (p:Person)
OPTIONAL MATCH (p)-[r]->(m)
RETURN p.name AS name,
       m:!CEO AS doesNotWorkDirectlyForTheCEO
name doesNotWorkDirectlyForTheCEO

"Alice"

true

"Cecil"

true

"Cecilia"

true

"Charlie"

true

"Daniel"

false

"Eskil"

null

Rows: 6

The function coalesce allows to turn null into a default value:

MATCH (p:Person)
OPTIONAL MATCH (p)-[r]->(m)
RETURN p.name AS name,
       coalesce(m:!CEO, false) AS doesNotWorkDirectlyForTheCEO
name doesNotWorkDirectlyForTheCEO

"Alice"

true

"Cecil"

true

"Cecilia"

true

"Charlie"

true

"Daniel"

false

"Eskil"

false

Rows: 6

Test whether a node matches a dynamic label expression

If you don’t know the manager labels, you can infer a list of managerLabels by collecting all non-Person labels from people with a direct report. You can test nodes with the label expression predicate to match a dynamic label expression. p:$any(managerLabels) tests whether a node p has at least on of the label in the list managerLabels.

MATCH ()-[r]->(p:Person)
UNWIND labels(p) AS label
FILTER label <> "Person"
RETURN COLLECT(label) AS managerLabels
NEXT
MATCH (p)
RETURN p.name AS name, p:$any(managerLabels) AS isManager
name isManager

"Alice"

true

"Cecil"

false

"Cecilia"

false

"Charlie"

false

"Daniel"

true

"Eskil"

true

Rows: 6

Examples using IS [NOT] LABELED

Test a node with IS LABELED
MATCH (p:Person)
RETURN p.name AS name, p IS LABELED Manager AS isManager
name isManager

"Alice"

true

"Cecil"

false

"Cecilia"

false

"Charlie"

false

"Daniel"

false

"Eskil"

false

Rows: 6

Simple CASE with IS LABELED branches
MATCH (p:Person)
RETURN p.name AS name,
       CASE p
         WHEN IS LABELED CEO THEN 'executive'
         WHEN IS LABELED Manager|Director THEN 'lead'
         ELSE 'ic'
       END AS role
ORDER BY name
name role

"Alice"

"lead"

"Cecil"

"ic"

"Cecilia"

"ic"

"Charlie"

"ic"

"Daniel"

"lead"

"Eskil"

"executive"

Rows: 6

Test whether a relationship has a certain relationship type

Given that r is a relationship, r:WORKS_FOR tests whether r has the relationship type WORKS_FOR or not and result in true or false, respectively.

MATCH (p:Person)-[r]->()
RETURN p.name AS name,
       r:WORKS_FOR AS isNotManager
name isNotManager

"Alice"

false

"Cecil"

true

"Cecilia"

true

"Charlie"

true

"Daniel"

false

Rows: 5

If r is null, then the label expression predicate, e.g. r:WORKS_FOR|REPORTS_TO, results in null. The function coalesce allows to turn null into a default value.

MATCH (p:Person)
OPTIONAL MATCH ()-[r]->(p)
RETURN DISTINCT
  p.name AS name,
  coalesce(r:WORKS_FOR|REPORTS_TO, false) AS hasReports
name hasReports

"Alice"

true

"Cecil"

false

"Cecilia"

false

"Charlie"

false

"Daniel"

true

"Eskil"

true

Rows: 6