Skip to content

Commit

Permalink
Improve Path Pattern Expression documentation (#723) (#801)
Browse files Browse the repository at this point in the history
https://trello.com/c/c0SxcchB/2009-clarify-restriction-of-single-node-pattern-in-where-clauses

---------

Co-authored-by: Daniel Leaver <daniel.leaver@neotechnology.com>
  • Loading branch information
JPryce-Aklundh and AzuObs authored Nov 28, 2023
1 parent 93a7be9 commit 534305a
Showing 1 changed file with 26 additions and 52 deletions.
78 changes: 26 additions & 52 deletions modules/ROOT/pages/clauses/where.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -479,33 +479,35 @@ The `name` and `age` for `Andy` are returned because his name starts with 'AND'
2+|Rows: 1
|===

[[path-pattern-expressions]]
== Path pattern expressions

[[query-where-patterns]]
== Using path patterns in `WHERE`
Similar to xref::subqueries/existential.adoc[existential subqueries], path pattern expressions can be used to assert whether a specified path exists at least once in a graph.
While existential subqueries are more powerful and capable of performing anything achievable with path pattern expressions, path pattern expressions are more concise.

[[filter-on-patterns]]
=== Filter on patterns
Path pattern expressions have the following restrictions (use cases that require extended functionality should consider using xref::subqueries/existential.adoc[existential subqueries] instead):

* Path pattern expressions may only use a subset of xref::patterns/reference.adoc#graph-patterns[graph pattern] semantics.

* A path pattern expression must be a xref::patterns/reference.adoc#path-patterns[path pattern] of length greater than zero.
In other words, it must contain at least one xref::patterns/reference.adoc#relationship-patterns[relationship] or xref::patterns/reference.adoc#variable-length-relationships[variable-length relationship].

Patterns are expressions in Cypher, expressions that return a list of paths.
List expressions are also predicates; an empty list represents `false`, and a non-empty list represents `true`.
* Path pattern expressions may not declare new variables.
They can only reference existing variables.

Patterns are not only expressions, they are also predicates.
The only limitation to a pattern is that it must be able to express it in a single path.
Unlike `MATCH`, it is not possible to use commas between multiple paths.
To combine multiple patterns using `WHERE`, instead use `AND`.
Note that new variables cannot be introduced.
Although it might look very similar to the `MATCH` patterns, the `WHERE` clause is used to eliminate matched paths.
`MATCH (a)-[*]->(b)` is very different from `WHERE (a)-[*]->(b)`.
The first will produce a path for every path it can find between `a` and `b`, whereas the latter will eliminate any matched paths where `a` and `b` do not have a directed relationship chain between them.
* Path pattern expressions may only be used in positions where a xref:queries/expressions.adoc#boolean[boolean expression] is expected.
The following sections will demonstrate how to use path pattern expressions in a `WHERE` clause.

[[filter-on-patterns]]
=== Filter on patterns

.Query
[source, cypher]
----
MATCH
(timothy:Person {name: 'Timothy'}),
(other:Person)
WHERE other.name IN ['Andy', 'Peter'] AND (other)-->(timothy)
WHERE (other)-->(timothy)
RETURN other.name, other.age
----

Expand All @@ -529,18 +531,18 @@ The `NOT` operator can be used to exclude a pattern:
[source, cypher]
----
MATCH
(person:Person),
(peter:Person {name: 'Peter'})
WHERE NOT (person)-->(peter)
RETURN person.name, person.age
(peter:Person {name: 'Peter'}),
(other:Person)
WHERE NOT (other)-->(peter)
RETURN other.name, other.age
----

The `name` and `age` values for nodes that do not have an outgoing relationship to `Peter` are returned:

.Result
[role="queryresult",options="header,footer",cols="2*<m"]
|===
| person.name | person.age
| other.name | other.age
| "Timothy" | 25
| "Peter" | 35
2+|Rows: 2
Expand All @@ -555,49 +557,21 @@ Properties can also be added to patterns:
.Query
[source, cypher]
----
MATCH (n:Person)
WHERE (n)-[:KNOWS]-({name: 'Timothy'})
RETURN n.name, n.age
MATCH (other:Person)
WHERE (other)-[:KNOWS]-({name: 'Timothy'})
RETURN other.name, other.age
----

The `name` and `age` values are returned for nodes that have a relationship with the type `KNOWS` connected to `Timothy`:

.Result
[role="queryresult",options="header,footer",cols="2*<m"]
|===
| n.name | n.age
| other.name | other.age
| "Andy" | 36
2+|Rows: 1
|===


[[filter-on-relationship-type]]
=== Filter on relationship type

You can put the exact relationship type in the `MATCH` pattern,
It also possible to do more advanced filtering on the relationship type by using 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
[source, cypher]
----
MATCH (n:Person)-[r]->()
WHERE n.name='Andy' AND type(r) =~ 'K.*'
RETURN type(r), r.since
----

This returns all relationships having a type whose name starts with 'K':

.Result
[role="queryresult",options="header,footer",cols="2*<m"]
|===
| type(r) | r.since
| "KNOWS" | 1999
| "KNOWS" | 2012
2+|Rows: 2
|===


[[query-where-lists]]
== Lists

Expand Down

0 comments on commit 534305a

Please sign in to comment.