diff --git a/modules/ROOT/content-nav.adoc b/modules/ROOT/content-nav.adoc index a8e62af55..af4174900 100644 --- a/modules/ROOT/content-nav.adoc +++ b/modules/ROOT/content-nav.adoc @@ -76,6 +76,7 @@ *** xref:expressions/predicates/comparison-operators.adoc[] *** xref:expressions/predicates/list-operators.adoc[] *** xref:expressions/predicates/string-operators.adoc[] +*** xref:expressions/predicates/label-expression-predicates.adoc[] *** xref:expressions/predicates/path-pattern-expressions.adoc[] *** xref:expressions/predicates/type-predicate-expressions.adoc[] ** xref:expressions/node-relationship-operators.adoc[] diff --git a/modules/ROOT/images/label_expression_predicates_graph.svg b/modules/ROOT/images/label_expression_predicates_graph.svg new file mode 100644 index 000000000..8abece4ef --- /dev/null +++ b/modules/ROOT/images/label_expression_predicates_graph.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/pages/expressions/index.adoc b/modules/ROOT/pages/expressions/index.adoc index 3e02f1d16..2deab8b38 100644 --- a/modules/ROOT/pages/expressions/index.adoc +++ b/modules/ROOT/pages/expressions/index.adoc @@ -10,6 +10,7 @@ For details and examples of specific expressions, see the following sections: ** xref:expressions/predicates/comparison-operators.adoc[]: `=`, `<>`, `<`, `>`, `\<=`, `>=`, `IS NULL`, `IS NOT NULL` ** xref:expressions/predicates/list-operators.adoc[]: `IN` ** xref:expressions/predicates/string-operators.adoc[]: `STARTS WITH`, `ENDS WITH`, `CONTAINS`, `IS NORMALIZED`, `IS NOT NORMALIZED`, `=~` +** xref:expressions/predicates/label-expression-predicates.adoc[]: information about how to test whether a node or relationship matches a label expression or not. ** xref:expressions/predicates/path-pattern-expressions.adoc[]: information about filtering queries with path pattern expressions. ** xref:expressions/predicates/type-predicate-expressions.adoc[]: information about how to verify the value type of a Cypher expression. * xref:expressions/node-relationship-operators.adoc[]: information about how to access `NODE` and `RELATIONSHIP` property values with `.` and `[]`. diff --git a/modules/ROOT/pages/expressions/predicates/index.adoc b/modules/ROOT/pages/expressions/predicates/index.adoc index ce68429c0..de890feb8 100644 --- a/modules/ROOT/pages/expressions/predicates/index.adoc +++ b/modules/ROOT/pages/expressions/predicates/index.adoc @@ -9,6 +9,7 @@ This chapter is divided into the following sections: * xref:expressions/predicates/comparison-operators.adoc[]: `=`, `<>`, `<`, `>`, `\<=`, `>=`, `IS NULL`, `IS NOT NULL` * xref:expressions/predicates/list-operators.adoc[]: `IN` * xref:expressions/predicates/string-operators.adoc[]: `STARTS WITH`, `ENDS WITH`, `CONTAINS`, `IS NORMALIZED`, `IS NOT NORMALIZED`, `=~` +* xref:expressions/predicates/label-expression-predicates.adoc[]: information about how to test whether a node or relationship matches a label expression or not. * xref:expressions/predicates/path-pattern-expressions.adoc[]: information about filtering queries with path pattern expressions. * xref:expressions/predicates/type-predicate-expressions.adoc[]: information about how to verify the value type of a Cypher expression. diff --git a/modules/ROOT/pages/expressions/predicates/label-expression-predicates.adoc b/modules/ROOT/pages/expressions/predicates/label-expression-predicates.adoc new file mode 100644 index 000000000..121072293 --- /dev/null +++ b/modules/ROOT/pages/expressions/predicates/label-expression-predicates.adoc @@ -0,0 +1,243 @@ += Label expression predicates +:description: This page describes how to use label expression predicates with Cypher. + +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. + +[[label-expression-predicat-syntax]] +== Syntax + +[source, syntax] +---- +: +---- + +Where `` is any Cypher expression and `` is any Cypher xref::patterns/reference.adoc#label-expressions[label expression]. + +[[example-graph]] +== Example graph + +The following graph is used for the examples on this page: + +image::label_expression_predicates_graph.svg[width="700",role="middle"] + +To recreate the graph, run the following query against an empty Neo4j database: + +[source, cypher] +---- +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) +---- + +[node-label-expression-predicate] +== 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. + +[source, cypher] +---- +MATCH (p:Person) +RETURN p.name AS name, p:Manager AS isManager +---- + +[role="queryresult",options="header,footer",cols="2*(m) +RETURN p.name AS name, + m:!CEO AS doesNotWorkDirectlyForTheCEO +---- + +[role="queryresult",options="header,footer",cols="2*` results in ´null`, then the label expression predicate results in `null`, e.g. if `p` is `null`, then `p:!CEO` results in `null`. + +[source, cypher] +---- +MATCH (p:Person) +OPTIONAL MATCH (p)-[r]->(m) +RETURN p.name AS name, + m:!CEO AS doesNotWorkDirectlyForTheCEO +---- + +[role="queryresult",options="header,footer",cols="2*(m) +RETURN p.name AS name, + coalesce(m:!CEO, false) AS doesNotWorkDirectlyForTheCEO +---- + +[role="queryresult",options="header,footer",cols="2*(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 +---- + +[role="queryresult",options="header,footer",cols="2*() +RETURN p.name AS name, + r:WORKS_FOR AS isNotManager +---- + +[role="queryresult",options="header,footer",cols="2*(p) +RETURN DISTINCT + p.name AS name, + coalesce(r:WORKS_FOR|REPORTS_TO, false) AS hasReports +---- + +[role="queryresult",options="header,footer",cols="2*(:Person {name: "Alice"})) A 1+d|Rows: 1 |=== + +[[not-patterns]] +== Expressions similar to path pattern expressions + +Since any expression can be wrapped in parentheses, some are very similar to path pattern expressions. +For example: + +`(p:Person)` is not a path pattern expression since it does not have at least one xref::patterns/reference.adoc#relationship-patterns[relationship] or xref::patterns/reference.adoc#variable-length-relationships[variable-length relationship]. +Instead, `(p:Person)` is the xref:expressions/predicates/label-expression-predicates.adoc[label expression predicate] `p:Person` in parentheses. + +.Parenthesized label expression predicate +[source, cypher] +---- +MATCH (employee:Person)-[:WORKS_FOR]->(p) + WHERE (p:Person) +RETURN employee.name AS employee, (p:Person) AS workForAPeron +---- + +The query result however is the same for both `p:Person` and `(p:Person)`: +[source, cypher] +---- +MATCH (employee:Person)-[:WORKS_FOR]->(p) + WHERE p:Person +RETURN employee.name AS employee, p:Person AS workForAPerson +---- + +.Result +[role="queryresult",options="header,footer",cols="2*(p) + WHERE (p) +RETURN employee.name AS employee +---- + +[source, error] +---- +Invalid input 'Node' for `p`. Expected to be Boolean. +---- \ No newline at end of file