Skip to content

Commit f4ed81e

Browse files
second
1 parent 5f2a64b commit f4ed81e

File tree

5 files changed

+157
-33
lines changed

5 files changed

+157
-33
lines changed

modules/ROOT/pages/appendix/gql-conformance/analogous-cypher.adoc

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,6 @@ These codes order the features in the table below.
3131
| * GQL's `PERCENTILE_CONT()` function is equivalent to Cypher's xref:functions/aggregating.adoc#functions-percentilecont[`percentileCont()`] function.
3232
* GQL's `PERCENTILE_DISC()` function is equivalent to Cypher's xref:functions/aggregating.adoc#functions-percentiledisc[`percentileDisc()`] function.
3333

34-
| GQ08
35-
| `FILTER` statement
36-
| Selects a subset of the records of the current working table.
37-
Cypher uses xref:clauses/with.adoc[`WITH`] instead.
38-
3934
| GQ09
4035
| `LET` statement
4136
| Adds columns to the current working table.
Lines changed: 133 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
= FILTER
2-
:description:
2+
:description: Information about Cypher's `FILTER` clause.
3+
:table-caption!:
4+
:page-role: new-2025.03
5+
6+
`FILTER` is used to add filters to queries, similar to Cypher's xref:clauses/where.adoc[`WHERE`] subclause.
7+
Unlike `WHERE`, `FILTER` is not a subclause, which means it can be used outside of the context of the xref:clauses/match.adoc[`MATCH`], xref:clauses/optional-match.adoc[`OPTIONAL MATCH`], and xref:clauses/with.adoc[`WITH`] clauses.
8+
It is not, however, as versatile as `WHERE`.
39

410
[[example-graph]]
511
== Example graph
@@ -26,54 +32,140 @@ CREATE (andy:Swedish:Person {name: 'Andy', age: 36}),
2632
----
2733

2834

35+
[[basic-filtering]]
2936
== Basic filtering
3037

38+
.Filter on a node label
39+
[source, cypher]
40+
----
3141
MATCH (n)
3242
FILTER n:Swedish
3343
RETURN n.name AS name
44+
----
45+
46+
.Result
47+
[role="queryresult",options="header,footer",cols="1*<m"]
48+
|===
49+
| name
50+
51+
| "Andy"
52+
53+
1+|Rows: 1
54+
|===
3455

56+
.Filter on a node property
57+
[source, cypher]
58+
----
3559
MATCH (n:Person)
3660
FILTER n.age < 35
3761
RETURN n.name AS name, n.age AS age
62+
----
63+
64+
.Result
65+
[role="queryresult",options="header,footer",cols="2*<m"]
66+
|===
67+
| name | age
3868

69+
| "Susan" | 32
70+
71+
2+|Rows: 1
72+
|===
73+
74+
.Filter on a relationship property
75+
[source, cypher]
76+
----
3977
MATCH (p:Person)-[r:KNOWS]->(n:Person)
40-
FILTER r.since > 2000
41-
RETURN p.name, n.name
78+
FILTER r.since > 2010
79+
RETURN p.name AS person,
80+
r.since AS knowsSince,
81+
n.name AS otherPerson
82+
----
83+
84+
.Result
85+
[role="queryresult",options="header,footer",cols="3*<m"]
86+
|===
87+
| person | knowsSince | otherPerson
88+
89+
| "Andy" | 2012 | "Timothy"
90+
| "John" | 2021 | "Susan"
4291

92+
3+|Rows: 2
93+
|===
94+
95+
[[filter-on-dynamic-properties]]
4396
== Filter on dynamic properties
4497

98+
To filter on a property using a dynamically computed name, use square brackets `[]`:
99+
100+
.Parameters
101+
[source, parameters]
102+
----
103+
{
104+
"propname": "age"
105+
}
106+
----
107+
108+
.Filter on a dynamically computed node property
109+
[source, cypher]
110+
----
45111
MATCH (n:Person)
46112
FILTER n[$propname] > 40
47113
RETURN n.name AS name, n.age AS age
114+
----
115+
116+
.Result
117+
[role="queryresult",options="header,footer",cols="2*<m"]
118+
|===
119+
| name | age
120+
121+
| "Lisa" | 48
48122

49-
== `WITH`, `WHERE`, and `FILTER`
123+
2+d|Rows: 1
124+
|===
50125

51-
=== FILTER as a substitute for `WITH * WHERE`
52-
* Filter makes WITH * WHERE ... redundant
126+
[[filter-with-where]]
127+
== `FILTER` replacing `WITH * WHERE`
53128

129+
Unlike `WHERE`, which relies on `MATCH`, `OPTIONAL MATCH`, or `WITH` to define its scope, `FILTER` -- being a clause rather than a subclause -- can filter queries independently of these clauses.
130+
This can make some queries more concise.
131+
132+
For example, the following two queries are equivalent:
133+
134+
.Filter using `WITH * WHERE`
135+
[source, cypher]
136+
----
54137
UNWIND [1, 2, 3, 4, 5, 6] AS x
55138
WITH x
56139
WHERE x > 2
57140
RETURN x
141+
----
58142

59-
same as
60-
143+
.Filter using `FILTER`
144+
[source, cypher]
145+
----
61146
UNWIND [1, 2, 3, 4, 5, 6] AS x
62-
FILTER > 2
147+
FILTER x > 2
63148
RETURN x
149+
----
150+
151+
As such, `FILTER` can be seen as a substitute for the `WITH * WHERE <predicate>` constructs in Cypher.
152+
153+
.Using `FILTER` instead of `WITH * WHERE` in `LOAD CSV`
154+
=====
64155
65-
load csv
156+
The following two xref:clauses/load-csv.adoc[`LOAD CSV`] commands are equivalent:
66157
67158
.companies.csv
68159
[source, csv, filename="companies.csv"]
69160
----
70161
Id,Name,Location,Email,BusinessType
71162
1,Neo4j,San Mateo,[email protected],P
72163
73-
3,BBB,Chicago, ,G
164+
3,BBB,Chicago, info@ ,G
74165
,CCC,Michigan,[email protected],G
75166
----
76167
168+
.`LOAD CSV` using `WITH * WHERE`
77169
[source, cypher]
78170
----
79171
LOAD CSV WITH HEADERS FROM 'file:///companies.csv' AS row
@@ -82,32 +174,48 @@ WHERE row.Id IS NOT NULL
82174
MERGE (c:Company {id: row.Id})
83175
----
84176
177+
.`LOAD CSV` using `FILTER`
85178
[source, cypher]
86179
----
87180
LOAD CSV WITH HEADERS FROM 'file:///companies.csv' AS row
88181
FILTER row.Id IS NOT NULL
89182
MERGE (c:Company {id: row.Id})
90183
----
91184
185+
=====
92186

93-
* Variable scope
94-
95-
96-
* Filter cannot exist in patterns
97-
187+
[[limitations]]
188+
== Limitations
98189

190+
While `FILTER` replaces `WITH * WHERE <predicate>` constructs, it does not include the ability of `WITH` to manipulate the variables in scope for subsequent clauses.
191+
Nor can `FILTER` alias or create new variables.
192+
In other words, `FILTER` only has the function of `WITH * WHERE <predicate>` not `WITH <selectedVariable> AS <newVariableName> WHERE <predicate>`.
99193

194+
Unlike `WHERE`, `FILTER` cannot be used to add filters to patterns.
100195

196+
.`WHERE` inside a node pattern
197+
[source, cypher]
198+
----
199+
WITH 35 AS minAge
200+
MATCH (a:Person WHERE a.name = 'Andy')-[:KNOWS]->(b:Person WHERE b.age > minAge)
201+
RETURN b.name AS name`
202+
----
203+
.Result
204+
[role="queryresult",options="header,footer",cols="1*<m"]
205+
|===
206+
| name
101207

208+
| "Timothy"
102209

210+
1+d|Rows: 1
211+
|===
103212

213+
.Not allowed -- `FILTER` inside a pattern
214+
[source, cypher, role=test-fail]
215+
----
216+
WITH 35 AS minAge
217+
MATCH (a:Person FILTER a.name = 'Andy')-[:KNOWS]->(b:Person FILTER b.age > minAge)
218+
RETURN b.name AS name
219+
----
104220

105-
106-
107-
108-
109-
== Differences between `FILTER` and `WHERE`
110-
111-
112-
113-
221+
For more information about how to use `WHERE` in fixed-length and variable-length pattern matching, see xref:clauses/where.adoc#filter-patterns[`WHERE` -> Filter patterns].

modules/ROOT/pages/clauses/load-csv.adoc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,9 @@ Neo4j does not store `null` values.
551551
In the file `companies.csv`, some rows do not specify values for some columns.
552552
The examples show several options of how to handle `null` values.
553553
554+
[NOTE]
555+
The queries in this example use xref:clauses/filter.adoc#filter-with-where[`FILTER`] (introduced in Neo4j 2025.03) as a replacement for `WITH * WHERE <predicate>`.
556+
554557
.companies.csv
555558
[source, csv, filename="companies.csv"]
556559
----

modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,10 +211,26 @@ label:new[]
211211

212212
[source, cypher, role="noheader"]
213213
----
214+
UNWIND [1, 2, 3, 4, 5, 6] AS x
215+
FILTER x > 2
216+
RETURN x
217+
----
214218

219+
[source, cypher, role="noheader"]
220+
----
221+
UNWIND [1, 2, 3, 4, 5, 6] AS x
222+
FILTER x > 2
223+
RETURN x
224+
----
225+
226+
[source, cypher, role="noheader"]
227+
----
228+
LOAD CSV WITH HEADERS FROM 'file:///companies.csv' AS row
229+
FILTER row.Id IS NOT NULL
230+
MERGE (c:Company {id: row.Id})
215231
----
216232

217-
| New xref:clauses/filter.adoc[`FILTER`] clause.
233+
| New xref:clauses/filter.adoc[`FILTER`] clause used to filter queries, similar to xref:clauses/where.adoc[`WHERE`].
218234

219235
a|
220236
label:functionality[]

modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,9 @@ RETURN status.transactionId AS transaction, status.committed AS commitStatus, st
748748
=====
749749
While failed transactions may be more efficiently retried using a link:{neo4j-docs-base-uri}/create-applications[driver], below is an example how failed transactions can be retried within the same Cypher query:
750750

751+
[NOTE]
752+
The query below uses xref:clauses/filter.adoc#filter-with-where[`FILTER`] (introduced in Neo4j 2025.03) as a replacement for `WITH * WHERE <predicate>`.
753+
751754
.Query retrying failed transactions
752755
[source, cypher]
753756
----
@@ -757,8 +760,7 @@ CALL (row) {
757760
MERGE (y:Year {year: row.year})
758761
MERGE (m)-[r:RELEASED_IN]->(y)
759762
} IN 2 CONCURRENT TRANSACTIONS OF 10 ROWS ON ERROR CONTINUE REPORT STATUS as status
760-
WITH *
761-
WHERE status.committed = false
763+
FILTER status.committed = false
762764
CALL (row) {
763765
MERGE (m:Movie {movieId: row.movieId})
764766
MERGE (y:Year {year: row.year})

0 commit comments

Comments
 (0)