From 6cb445d0646c563e54faaec39d051cb384a581f2 Mon Sep 17 00:00:00 2001 From: JPryce-Aklundh Date: Fri, 27 Jan 2023 11:10:46 +0100 Subject: [PATCH 1/4] first update --- modules/ROOT/pages/clauses/call-subquery.adoc | 78 +++++++++---------- 1 file changed, 35 insertions(+), 43 deletions(-) diff --git a/modules/ROOT/pages/clauses/call-subquery.adoc b/modules/ROOT/pages/clauses/call-subquery.adoc index 3e15b6631..bbff07336 100644 --- a/modules/ROOT/pages/clauses/call-subquery.adoc +++ b/modules/ROOT/pages/clauses/call-subquery.adoc @@ -36,7 +36,10 @@ The following graph is used for the examples below: image:graph_call_subquery_clause.svg[] -//// +To recreate the graph, run the following query in an empty Neo4j database: + +[source, cypher, role=test-setup] +---- CREATE (a:Person:Child {age: 20, name: 'Alice'}), (b:Person {age: 27, name: 'Bob'}), @@ -45,7 +48,7 @@ CREATE CREATE (a)-[:FRIEND_OF]->(b) CREATE (a)-[:CHILD_OF]->(c) CREATE (:Counter {count: 0}) -//// +---- [[call-semantics]] @@ -70,22 +73,16 @@ RETURN innerReturn ---- .Result -[source, result, role="noheader"] ----- -Rows: 3 - -+-------------+ -| innerReturn | -+-------------+ -| 'hello' | -| 'hello' | -| 'hello' | -+-------------+ ----- - +[role="queryresult",options="header,footer",cols="m"] +|=== +| +innerReturn+ +| +'hello'+ +| +'hello'+ +| +'hello'+ +d|Rows:3 +|=== ====== - Each execution of a `CALL` clause can observe changes from previous executions. @@ -109,19 +106,19 @@ RETURN ---- .Result -[source, result, role="noheader"] ----- -Set Properties: 3 -Rows: 3 +[role="queryresult",options="header,footer",cols=""2* Date: Fri, 27 Jan 2023 14:06:17 +0100 Subject: [PATCH 2/4] fix examples --- modules/ROOT/pages/clauses/call-subquery.adoc | 37 +++++++++++++------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/modules/ROOT/pages/clauses/call-subquery.adoc b/modules/ROOT/pages/clauses/call-subquery.adoc index bbff07336..492f74314 100644 --- a/modules/ROOT/pages/clauses/call-subquery.adoc +++ b/modules/ROOT/pages/clauses/call-subquery.adoc @@ -125,6 +125,7 @@ RETURN [[subquery-correlated-importing]] == Importing variables into subqueries +====== Variables are imported into a subquery using an importing `WITH` clause. As the subquery is evaluated for each incoming input row, the imported variables get bound to the corresponding values from the input row in each evaluation. @@ -160,6 +161,7 @@ An importing `WITH` clause must: The order in which subqueries are executed is not defined. If a query result depends on the order of execution of subqueries, an `ORDER BY` clause should precede the `CALL` clause. ==== +====== .The order in which subqueries are executed @@ -201,9 +203,9 @@ RETURN | +"Alice"+ | +20+ | +"Bob"+ | +27+ | +"Bob"+ | +27+ | +"Dora"+ | +30+ -| +"Dora"+ | +30+ | +"Bob"+ | +65+ +| +"Dora"+ | +30+ | +"Charlie"+ | +65+ -3+d|Rows: 3 +4+d|Rows: 3 |=== ====== @@ -211,7 +213,7 @@ RETURN [[subquery-post-union]] == Post-union processing - +====== Subqueries can be used to process the results of a `UNION` query further. This example query finds the youngest and the oldest person in the database and orders them by name. @@ -273,7 +275,7 @@ RETURN DISTINCT p.name, count(other) | +"Dora"+ | +0+ 2+d|Rows: 4 |=== - +====== [[subquery-aggregation]] == Aggregations @@ -324,10 +326,10 @@ RETURN p.name, numberOfConnections [role="queryresult",options="header,footer",cols="2* Date: Fri, 27 Jan 2023 14:22:52 +0100 Subject: [PATCH 3/4] more updates --- modules/ROOT/pages/clauses/call-subquery.adoc | 84 ++++++++----------- 1 file changed, 36 insertions(+), 48 deletions(-) diff --git a/modules/ROOT/pages/clauses/call-subquery.adoc b/modules/ROOT/pages/clauses/call-subquery.adoc index 492f74314..0efdeac4c 100644 --- a/modules/ROOT/pages/clauses/call-subquery.adoc +++ b/modules/ROOT/pages/clauses/call-subquery.adoc @@ -57,13 +57,13 @@ CREATE (:Counter {count: 0}) A `CALL` clause is executed once for each incoming row. -.Execute for each incomming row +.Execute for each incoming row ====== The `CALL` clause executes three times, one for each row that the `UNWIND` clause outputs. .Query -[source, cypher, role="noplay"] +[source, cypher] ---- UNWIND [0, 1, 2] AS x CALL { @@ -90,7 +90,7 @@ Each execution of a `CALL` clause can observe changes from previous executions. ====== .Query -[source, cypher, role="noplay"] +[source, cypher] ---- UNWIND [0, 1, 2] AS x CALL { @@ -125,13 +125,12 @@ RETURN [[subquery-correlated-importing]] == Importing variables into subqueries -====== Variables are imported into a subquery using an importing `WITH` clause. As the subquery is evaluated for each incoming input row, the imported variables get bound to the corresponding values from the input row in each evaluation. .Query -[source, cypher, indent=0] +[source, cypher] ---- UNWIND [0, 1, 2] AS x CALL { @@ -161,7 +160,6 @@ An importing `WITH` clause must: The order in which subqueries are executed is not defined. If a query result depends on the order of execution of subqueries, an `ORDER BY` clause should precede the `CALL` clause. ==== -====== .The order in which subqueries are executed @@ -172,7 +170,7 @@ This query creates a linked list of all `:Person` nodes in order of ascending ag The `CALL` clause is relying on the incoming row ordering to ensure that a correctly linked list is created, thus the incoming rows must be ordered with a preceding `ORDER BY` clause. .Query -[source, cypher, role="noplay"] +[source, cypher] ---- MATCH (person:Person) WITH person ORDER BY person.age ASC LIMIT 1 @@ -213,13 +211,12 @@ RETURN [[subquery-post-union]] == Post-union processing -====== Subqueries can be used to process the results of a `UNION` query further. This example query finds the youngest and the oldest person in the database and orders them by name. .Query -[source, cypher, indent=0] +[source, cypher] ---- CALL { MATCH (p:Person) @@ -250,7 +247,7 @@ This example query finds friends and/or parents for each person. Subsequently the number of friends and parents are counted together. .Query -[source, cypher, indent=0] +[source, cypher] ---- MATCH (p:Person) CALL { @@ -285,7 +282,7 @@ Returning subqueries change the number of results of the query: The result of th The following example finds the name of each person and the names of their friends: .Query -[source, cypher, indent=0] +[source, cypher] ---- MATCH (p:Person) CALL { @@ -311,7 +308,7 @@ We can also use subqueries to perform isolated aggregations. In this example we As we get one row from each evaluation of the subquery, the number of rows is the same, before and after the `CALL` clause: .Query -[source, cypher, indent=0] +[source, cypher] ---- MATCH (p:Person) CALL { @@ -343,7 +340,7 @@ This example query creates five clones of each existing person. As the subquery is a unit subquery, it does not change the number of rows of the enclosing query. .Query -[source, cypher, indent=0] +[source, cypher] ---- MATCH (p:Person) CALL { @@ -365,6 +362,21 @@ Properties set: 20 + Labels added: 20 |=== +//// +[source, cypher, role=test-setup] +---- +MATCH (n) +DETACH DELETE n; +CREATE + (a:Person:Child {age: 20, name: 'Alice'}), + (b:Person {age: 27, name: 'Bob'}), + (c:Person:Parent {age: 65, name: 'Charlie'}), + (d:Person {age: 30, name: 'Dora'}), + (:Counter {count: 0}), + (a)-[:FRIEND_OF]->(b), + (a)-[:CHILD_OF]->(c) +---- +//// [[subquery-correlated-aggregation]] == Aggregation on imported variables @@ -373,7 +385,7 @@ Aggregations in subqueries are scoped to the subquery evaluation, also for impor The following example counts the number of younger persons for each person in the graph: .Query -[source, cypher, indent=0] +[source, cypher] ---- MATCH (p:Person) CALL { @@ -408,7 +420,7 @@ The following example uses a CSV file and the `LOAD CSV` clause to import more d It creates nodes in separate transactions using `+CALL { ... } IN TRANSACTIONS+`: .friends.csv -[source, csv, role="noheader"] +[source, csv] ---- 1,Bill,26 2,Max,27 @@ -418,7 +430,7 @@ It creates nodes in separate transactions using `+CALL { ... } IN TRANSACTIONS+` ---- .Query -[source, cypher, indent=0] +[source, cypher] ---- LOAD CSV FROM 'file:///friends.csv' AS line CALL { @@ -455,19 +467,8 @@ Using `+CALL { ... } IN TRANSACTIONS+` is the recommended way of deleting a larg .+DETACH DELETE+ ====== -//// -CREATE - (a:Person:Child {age: 20, name: 'Alice'}), - (b:Person {age: 27, name: 'Bob'}), - (c:Person:Parent {age: 65, name: 'Charlie'}), - (d:Person {age: 30, name: 'Dora'}), - (:Counter {count: 0}) - CREATE (a)-[:FRIEND_OF]->(b) - CREATE (a)-[:CHILD_OF]->(c) -//// - .Query -[source, cypher, indent=0] +[source, cypher] ---- MATCH (n) CALL { @@ -502,19 +503,8 @@ The `+CALL { ... } IN TRANSACTIONS+` subquery should not be modified. Any necessary filtering can be done before the subquery. -//// -CREATE - (a:Person:Child {age: 20, name: 'Alice'}), - (b:Person {age: 27, name: 'Bob'}), - (c:Person:Parent {age: 65, name: 'Charlie'}), - (d:Person {age: 30, name: 'Dora'}), - (:Counter {count: 0}) - CREATE (a)-[:FRIEND_OF]->(b) - CREATE (a)-[:CHILD_OF]->(c) -//// - .Query -[source, cypher, indent=0] +[source, cypher] ---- MATCH (n:Label) WHERE n.prop > 100 CALL { @@ -530,8 +520,6 @@ CALL { 1+d|Rows: 0 |=== -====== - === Batching @@ -552,7 +540,7 @@ The following is the same example but with one transaction every `2` input rows: ---- .Query -[source, cypher, indent=0] +[source, cypher] ---- LOAD CSV FROM 'file:///friends.csv' AS line CALL { @@ -585,7 +573,7 @@ You can also use `+CALL { ... } IN TRANSACTIONS OF n ROWS+` to delete all your d For example: .Query -[source, cypher, indent=0] +[source, cypher] ---- MATCH (n) CALL { @@ -637,7 +625,7 @@ RETURN i ---- .Error message -[source, error, role="noheader"] +[source, error] ---- / by zero (Transactions committed: 1) ---- @@ -645,7 +633,7 @@ RETURN i When the failure occurred, the first transaction had already been committed, so the database contains two example nodes. .Query -[source, cypher, indent=0] +[source, cypher] ---- MATCH (e:Example) RETURN e.num @@ -691,7 +679,7 @@ RETURN largeLists ---- .Error message -[source, output, role="noheader", indent=0] +[source, error] ---- Importing WITH should consist only of simple references to outside variables. WHERE is not allowed. @@ -702,7 +690,7 @@ This second `WITH` clause will act as a regular `WITH` clause. For example, the following query will not throw an error: .Query -[source, cypher, indent=0] +[source, cypher] ---- UNWIND [[1,2],[1,2,3,4],[1,2,3,4,5]] AS l CALL { From 95063bd9ecb8656213eb1302aade7c264dbedc48 Mon Sep 17 00:00:00 2001 From: JPryce-Aklundh Date: Fri, 27 Jan 2023 14:29:07 +0100 Subject: [PATCH 4/4] fix example boxes --- modules/ROOT/pages/clauses/call-subquery.adoc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/ROOT/pages/clauses/call-subquery.adoc b/modules/ROOT/pages/clauses/call-subquery.adoc index 0efdeac4c..34dd53746 100644 --- a/modules/ROOT/pages/clauses/call-subquery.adoc +++ b/modules/ROOT/pages/clauses/call-subquery.adoc @@ -272,7 +272,7 @@ RETURN DISTINCT p.name, count(other) | +"Dora"+ | +0+ 2+d|Rows: 4 |=== -====== + [[subquery-aggregation]] == Aggregations @@ -520,6 +520,8 @@ CALL { 1+d|Rows: 0 |=== +====== + === Batching