Skip to content

Commit 4c7d9a4

Browse files
WilcoNeorsill-neo4j
authored andcommitted
resolved merge conflict
1 parent 2b9d98c commit 4c7d9a4

File tree

1 file changed

+117
-3
lines changed

1 file changed

+117
-3
lines changed

modules/ROOT/pages/clauses/clause-composition.adoc

Lines changed: 117 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,13 +130,31 @@ The most important aspect of read-write queries is that the state of the graph a
130130

131131
[IMPORTANT]
132132
====
133-
A clause can never observe writes made by a later clause.
133+
A clause can never observe writes made by a later clause, and will observe all writes done by the previous clauses.
134134
====
135135

136+
As of Cypher 25, read and write clauses can be combined in any order.
137+
That is, a write clause followed by a read clause no longer requires a separating xref:clauses/with.adoc[`WITH`] clause in order for the read clause to observe the changes made by a preceding write clause.
138+
For example, the following query, in which the changes made by a write clause (xref:clauses/set.adoc[`SET`]) are observed by a subsequent `MATCH` clause without an intermediate `WITH` clause, is valid using Cypher 25 but not link:https://neo4j.com/docs/cypher-manual/current/clauses/with/#combine-write-and-read-clauses[Cypher 5].
139+
140+
141+
.Combine write and read clauses without a separating `WITH` clause
142+
[source, cypher]
143+
----
144+
MATCH (j:Person {name: 'John'})-[:FRIEND]->(f)
145+
SET f.degreesFromJohn = 1
146+
MATCH (f)-[:FRIEND]->(f2)
147+
SET f2.degreesFromJohn = f.degreesFromJohn + 1
148+
RETURN f.name AS friendName,
149+
f.degreesFromJohn AS friendDegree,
150+
f2.name AS friendOfFriendName,
151+
f2.degreesFromJohn AS friendOfFriendDegree
152+
----
153+
136154
.Table of intermediate results and state of the graph between read and write clauses
137155
======
138156
139-
Using the same example graph as above, this example shows the table of intermediate results and the state of the graph after each clause for the following query:
157+
Using the same example graph as above, this example shows the table of intermediate results and the state of the graph after each clause for a query with a read clause before a write clause:
140158
141159
[source,cypher, indent=0]
142160
----
@@ -147,7 +165,7 @@ The query finds all nodes where the `name` property starts with "J"
147165
and for each such node it creates another node with the `name` property set to "Jay-jay".
148166
149167
150-
.+The table of intermediate results and the state of the graph after each clause+
168+
.Read-write: The table of intermediate results and the state of the graph after each clause+
151169
[options="header", width="100%", cols="3a, 4a, 4a"]
152170
|===
153171
@@ -294,6 +312,102 @@ the graph made by the `CREATE`.
294312
295313
======
296314

315+
.Table of intermediate results and state of the graph between write and read clauses
316+
======
317+
On an empty graph, this example shows the table of intermediate results and the state of the graph after each clause for a query with a write clause before a read clause:
318+
319+
[source,cypher, indent=0]
320+
----
321+
UNWIND ["Max", "Lune"] AS dogName
322+
CREATE (n:Dog {name: dogName})
323+
WITH n
324+
MATCH (d:Dog)
325+
RETURN COUNT(*)
326+
----
327+
This query creates two `Dog` nodes and returns the value `4`.
328+
329+
.+Write-read: The table of intermediate results and the state of the graph after each clause+
330+
[options="header", width="100%", cols="3a, 4a, 4a"]
331+
|===
332+
333+
| Clause
334+
| Table of intermediate results after the clause
335+
| State of the graph after the clause, changes in red
336+
337+
| ----
338+
UNWIND ["Max", "Luna"] AS dogName
339+
----
340+
|
341+
[options="header",cols="1m"]
342+
!===
343+
! dogName
344+
! "Max"
345+
! "Luna"
346+
!===
347+
|
348+
349+
| ----
350+
CREATE (n:Dog {name: dogName})
351+
----
352+
|
353+
[options="header",cols="1m, 1m"]
354+
!===
355+
! dogName ! n
356+
! "Max" ! (:Dog {name: 'Max'})
357+
! "Luna" ! (:Dog {name: 'Luna'})
358+
!===
359+
|
360+
361+
[graphviz]
362+
----
363+
digraph L { node [shape=record style=rounded];
364+
N5 [
365+
color = "red"
366+
fontcolor = "red"
367+
label = "{Dog\|name = \'Max\'\l}"
368+
]
369+
N6 [
370+
color = "red"
371+
fontcolor = "red"
372+
label = "{Dog\|name = \'Luna\'\l}"
373+
]
374+
}
375+
----
376+
377+
| ----
378+
MATCH (d:Dog)
379+
----
380+
|
381+
[options="header",cols="1m, 1m, 1m"]
382+
!===
383+
! dogName ! n ! d
384+
! "Max" ! (:Dog {name: 'Max'}) ! (:Dog {name: 'Max'})
385+
! "Max" ! (:Dog {name: 'Max'}) ! (:Dog {name: 'Luna'})
386+
! "Luna" ! (:Dog {name: 'Luna'}) ! (:Dog {name: 'Max'})
387+
! "Luna" ! (:Dog {name: 'Luna'}) ! (:Dog {name: 'Luna'})
388+
!===
389+
|
390+
391+
[graphviz]
392+
----
393+
digraph L { node [shape=record style=rounded];
394+
N5 [
395+
label = "{Dog\|name = \'Max\'\l}"
396+
]
397+
N6 [
398+
label = "{Dog\|name = \'Luna\'\l}"
399+
]
400+
}
401+
----
402+
|===
403+
404+
It is important to note that the `MATCH` clause reads all the `Dog` nodes that are created by the `CREATE` clause.
405+
This is because the `CREATE` clause comes before the `MATCH` clause and thus the `MATCH` observes all changes to
406+
the graph made by the `CREATE`.
407+
The `MATCH` clause is performed for every intermediate result, this leads to finding two nodes for both intermediate results.
408+
409+
======
410+
297411
[[cypher-clause-composition-union-queries]]
298412
== Queries with `UNION`
299413

0 commit comments

Comments
 (0)