From 28544a7ee2117a5943e843ee1cf916420256367a Mon Sep 17 00:00:00 2001 From: Richard Sill Date: Fri, 25 Apr 2025 09:58:42 +0200 Subject: [PATCH 01/13] added a page for sequential queries with NEXT and the respective entries for additions and GQL conformance --- modules/ROOT/content-nav.adoc | 1 + .../gql-conformance/supported-optional.adoc | 10 +++++++++- ...cations-additions-removals-compatibility.adoc | 16 ++++++++++++++++ .../pages/queries/composed-queries/index.adoc | 9 ++++++--- .../composed-queries/sequential-queries.adoc | 12 ++++++++++++ modules/ROOT/pages/queries/index.adoc | 3 ++- package-lock.json | 3 ++- 7 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc diff --git a/modules/ROOT/content-nav.adoc b/modules/ROOT/content-nav.adoc index 1f2ddf6d0..aca26e744 100644 --- a/modules/ROOT/content-nav.adoc +++ b/modules/ROOT/content-nav.adoc @@ -9,6 +9,7 @@ ** xref:queries/composed-queries/index.adoc[] *** xref:queries/composed-queries/combined-queries.adoc[] *** xref:queries/composed-queries/conditional-queries.adoc[] +*** xref:queries/composed-queries/sequential-queries.adoc[] * xref:clauses/index.adoc[] ** xref:clauses/clause-composition.adoc[] diff --git a/modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc b/modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc index 0f930c4ab..7da7eec6b 100644 --- a/modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc +++ b/modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc @@ -46,7 +46,8 @@ These codes order the features in the table below. | G020 | Counted shortest group search | xref:patterns/shortest-paths.adoc#shortest-groups[`SHORTEST GROUPS`] -| +| + | G035 | Quantified paths @@ -188,6 +189,13 @@ For example, GQL’s graph reference values `CURRENT_GRAPH` and `CURRENT_PROPERT | xref:clauses/limit.adoc[`LIMIT`], xref:clauses/order-by.adoc[`ORDER BY`] | Cypher requires using the xref:clauses/with.adoc[`WITH`] clause, which GQL does not. +| GQ20 +| `NEXT` statement +| xref:queries/composed-queries/sequential-queries.adoc[] +| The GQL standard includes a `YIELD` clause for its `NEXT` statement. +The purpose of this `YIELD` clause is to ensure compatible behavior with SQL as it uses double quotes for delimiting identifiers. +Cypher on the other hand uses double quotes for strings and backticks for quoting and thus having a `YIELD` clause does not provide additional use in Cypher. + | GV39 | Temporal types: date, local datetime, and local time support | xref:values-and-types/temporal.adoc[Temporal types], xref:functions/temporal/index.adoc#functions-date[`date()`] diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index 9be462803..893cb40cc 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -224,6 +224,22 @@ a| label:functionality[] label:new[] +[source, cypher, role="noheader"] +---- +RETURN 1 AS a + +NEXT + +RETURN 1 AS b +---- + +| Introduction of `NEXT` which allows for linear composition of queries into a sequence. +For more information, see xref:queries/composed-queries/sequential-queries.adoc[]. + +a| +label:functionality[] +label:new[] + [source, cypher, role="noheader"] ---- MATCH (s:Supplier)-[:SUPPLIES]->(p:Product) diff --git a/modules/ROOT/pages/queries/composed-queries/index.adoc b/modules/ROOT/pages/queries/composed-queries/index.adoc index 297a2a78c..f234b72b9 100644 --- a/modules/ROOT/pages/queries/composed-queries/index.adoc +++ b/modules/ROOT/pages/queries/composed-queries/index.adoc @@ -1,11 +1,14 @@ = Composed queries :description: Overview about how to use `UNION` and `WHEN` to construct combined or conditional queries in Cypher. -`UNION` and `WHEN` enable the composition of multiple separate query branches within a single query. -`UNION` allows for combining the results of different queries, while `WHEN` enables conditional queries, where different query branches can be made to execute depending on a set of criteria. -As such, `UNION` and `WHEN` manage in different ways the execution flow and logic of queries and cannot be used in queries as regular clauses. +`UNION`, `WHEN` and `NEXT` enable the composition of multiple separate query branches within a single query. +`UNION` allows for combining the results of different queries. +`WHEN` on the other hand enables conditional queries, where different query branches can be made to execute depending on a set of criteria. +Finally, `NEXT` allows for linear composition of queries into a sequence, while making return values from one query available in the next. +As such, `UNION`, `WHEN` and `NEXT` manage in different ways the execution flow and logic of queries and cannot be used in queries as regular clauses. For more information, see: * xref:queries/composed-queries/combined-queries.adoc[] * xref:queries/composed-queries/conditional-queries.adoc[] label:new[Introduced in Neo4j 2025.06] +* xref:queries/composed-queries/sequential-queries.adoc[] label:new[Introduced in Neo4j 2025.06] diff --git a/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc b/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc new file mode 100644 index 000000000..eec314683 --- /dev/null +++ b/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc @@ -0,0 +1,12 @@ += Sequential queries (`NEXT`) +:description: Information about how to use `NEXT` to construct conditional queries in Cypher. +:page-role: new-2025.06 + +//// +Benefits to this proposal + +Increases the modularity (and readability) of Cypher — allows for the partition of large queries into smaller, self contained modules that are possible to chain together using NEXT. +Decreases the reliance on CALL and WITH for constructing complex queries. +Improves usability of conditional and union queries. +Improves Cypher GQL conformance. +//// \ No newline at end of file diff --git a/modules/ROOT/pages/queries/index.adoc b/modules/ROOT/pages/queries/index.adoc index 9e630f317..063e5f050 100644 --- a/modules/ROOT/pages/queries/index.adoc +++ b/modules/ROOT/pages/queries/index.adoc @@ -2,11 +2,12 @@ :description: This page is an overview of the queries section in the Cypher Manual. This section provides a brief overview of the core concepts of a Cypher query (nodes, relationships, and paths), and examples of how to query a Neo4j graph database. -It also discusses how to compose combined queries using `UNION` and conditional queries using `WHEN`. +It also discusses how to compose combined queries using `UNION`, conditional queries using `WHEN` and sequential queries using `NEXT`. * xref:queries/concepts.adoc[] * xref:queries/basic.adoc[] * xref:queries/composed-queries/index.adoc[] ** xref:queries/composed-queries/combined-queries.adoc[] ** xref:queries/composed-queries/conditional-queries.adoc[] label:new[Introduced in Neo4j 2025.06] +** xref:queries/composed-queries/sequential-queries.adoc[] label:new[Introduced in Neo4j 2025.06] diff --git a/package-lock.json b/package-lock.json index fb8fd9d50..e2fe81617 100644 --- a/package-lock.json +++ b/package-lock.json @@ -329,7 +329,8 @@ "node_modules/@neo4j-antora/antora-modify-sitemaps": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/@neo4j-antora/antora-modify-sitemaps/-/antora-modify-sitemaps-0.4.4.tgz", - "integrity": "sha512-IkXoilOJquZPB5G5ZhrgfSN6U3E2YToWakehtF55RA+CNQS0KboTAB2vUH01+Tkmkd8K6UElf41A6cGnnrvs0g==" + "integrity": "sha512-IkXoilOJquZPB5G5ZhrgfSN6U3E2YToWakehtF55RA+CNQS0KboTAB2vUH01+Tkmkd8K6UElf41A6cGnnrvs0g==", + "license": "MIT" }, "node_modules/@neo4j-antora/antora-page-roles": { "version": "0.3.2", From 6401f145835d4d6bde77028542df4308c1950f9d Mon Sep 17 00:00:00 2001 From: Richard Sill Date: Mon, 28 Apr 2025 18:53:13 +0200 Subject: [PATCH 02/13] intro + subsection headings for NEXT --- .../composed-queries/sequential-queries.adoc | 81 +++++++++++++++++-- 1 file changed, 73 insertions(+), 8 deletions(-) diff --git a/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc b/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc index eec314683..34c70e4d9 100644 --- a/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc +++ b/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc @@ -1,12 +1,77 @@ = Sequential queries (`NEXT`) -:description: Information about how to use `NEXT` to construct conditional queries in Cypher. +:description: Information about how to use `NEXT` to construct sequential queries in Cypher. :page-role: new-2025.06 -//// -Benefits to this proposal +`NEXT` allows for linear composition of queries into a sequence of smaller, self-contained segments while making return values from one segment available in the next. -Increases the modularity (and readability) of Cypher — allows for the partition of large queries into smaller, self contained modules that are possible to chain together using NEXT. -Decreases the reliance on CALL and WITH for constructing complex queries. -Improves usability of conditional and union queries. -Improves Cypher GQL conformance. -//// \ No newline at end of file +`NEXT` has a number of benefits: + +* `NEXT` can improve the modularity and readability of complex queries. +* `NEXT` reduces the need to rely on the xref:clauses/call.adoc[CALL] and xref:clauses/with.adoc[] clauses to construct complex queries. +* `NEXT` improves the usability of xref:queries/composed-queries/conditional-queries.adoc[conditional] and xref:queries/composed-queries/combined-queries.adoc[UNION] queries. + +`NEXT` was introduced as part of Cypher's xref:appendix/gql-conformance/index.adoc[]. + + + +[[example-graph]] +== Example graph + +The following graph is used for the examples on this page: + +image::conditional_query_graph.svg[width="700",role="middle"] + +To recreate the graph, run the following query against an empty Neo4j database: + +[source, cypher, role=test-setup] +---- +CREATE (alice:Person {name:'Alice', age: 65}), + (bob:Person {name: 'Bob', age: 25}), + (charlie:Person {name: 'Charlie', age: 61}), + (daniel:Person {name: 'Daniel', age: 39}), + (eskil:Person {name: 'Eskil', age: 39}), + (bob)-[:WORKS_FOR]->(alice), + (alice)-[:WORKS_FOR]->(daniel), + (charlie)-[:WORKS_FOR]->(daniel), + (bob)-[:LOVES]->(eskil), + (charlie)-[:LOVES]->(alice) +---- + + +[[sequential-syntax]] +== Syntax + +Lorem ipsum. + + +[[sequential-rules]] +== Rules + +Lorem ipsum. + +.Not allowed: not aliasing returned expressions +[source, cypher, role=test-fail] +---- +WHEN true THEN RETURN 2 +ELSE RETURN 3 +---- + + +== Using `NEXT` instead of `CALL` + +Lorem ipsum. + + +== Using `NEXT` instead of `WITH` + +Lorem ipsum. + + +== Interactions with conditional queries + +Lorem ipsum. + + +== Interactions with `UNION` queries + +Lorem ipsum. \ No newline at end of file From d23b1531a0ce39e76c626b2d8c163883428fd388 Mon Sep 17 00:00:00 2001 From: Richard Sill Date: Wed, 30 Apr 2025 18:35:42 +0200 Subject: [PATCH 03/13] fleshed out the sections a bit, examples need some updates still --- .../composed-queries/sequential-queries.adoc | 310 ++++++++++++++++-- 1 file changed, 279 insertions(+), 31 deletions(-) diff --git a/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc b/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc index 34c70e4d9..f1ae41199 100644 --- a/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc +++ b/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc @@ -1,14 +1,15 @@ = Sequential queries (`NEXT`) :description: Information about how to use `NEXT` to construct sequential queries in Cypher. +:table-caption!: :page-role: new-2025.06 `NEXT` allows for linear composition of queries into a sequence of smaller, self-contained segments while making return values from one segment available in the next. -`NEXT` has a number of benefits: +`NEXT` has the following benefits: * `NEXT` can improve the modularity and readability of complex queries. -* `NEXT` reduces the need to rely on the xref:clauses/call.adoc[CALL] and xref:clauses/with.adoc[] clauses to construct complex queries. -* `NEXT` improves the usability of xref:queries/composed-queries/conditional-queries.adoc[conditional] and xref:queries/composed-queries/combined-queries.adoc[UNION] queries. +* `NEXT` can be used instead of xref:subqueries/call-subquery.adoc[] and the xref:clauses/with.adoc[] clause to construct complex queries. +* `NEXT` can improve the usability of xref:queries/composed-queries/conditional-queries.adoc[conditional] and xref:queries/composed-queries/combined-queries.adoc[UNION] queries. `NEXT` was introduced as part of Cypher's xref:appendix/gql-conformance/index.adoc[]. @@ -19,59 +20,306 @@ The following graph is used for the examples on this page: -image::conditional_query_graph.svg[width="700",role="middle"] +image::with_clause.svg[width="600",role="middle"] -To recreate the graph, run the following query against an empty Neo4j database: +To recreate the graph, run the following query against an empty Neo4j database. [source, cypher, role=test-setup] ---- -CREATE (alice:Person {name:'Alice', age: 65}), - (bob:Person {name: 'Bob', age: 25}), - (charlie:Person {name: 'Charlie', age: 61}), - (daniel:Person {name: 'Daniel', age: 39}), - (eskil:Person {name: 'Eskil', age: 39}), - (bob)-[:WORKS_FOR]->(alice), - (alice)-[:WORKS_FOR]->(daniel), - (charlie)-[:WORKS_FOR]->(daniel), - (bob)-[:LOVES]->(eskil), - (charlie)-[:LOVES]->(alice) +CREATE (techCorp:Supplier {name: 'TechCorp', email: 'contact@techcorp.com'}), + (foodies:Supplier {name: 'Foodies Inc.', email: 'info@foodies.com'}), + + (laptop:Product {name: 'Laptop', price: 1000}), + (phone:Product {name: 'Phone', price: 500}), + (headphones:Product {name: 'Headphones', price: 250}), + (chocolate:Product {name: 'Chocolate', price: 5}), + (coffee:Product {name: 'Coffee', price: 10}), + + (amir:Customer {firstName: 'Amir', lastName: 'Rahman', email: 'amir.rahman@example.com', discount: 0.1}), + (keisha:Customer {firstName: 'Keisha', lastName: 'Nguyen', email: 'keisha.nguyen@example.com', discount: 0.2}), + (mateo:Customer {firstName: 'Mateo', lastName: 'Ortega', email: 'mateo.ortega@example.com', discount: 0.05}), + (hannah:Customer {firstName: 'Hannah', lastName: 'Connor', email: 'hannah.connor@example.com', discount: 0.15}), + (leila:Customer {firstName: 'Leila', lastName: 'Haddad', email: 'leila.haddad@example.com', discount: 0.1}), + (niko:Customer {firstName: 'Niko', lastName: 'Petrov', email: 'niko.petrov@example.com', discount: 0.25}), + (yusuf:Customer {firstName: 'Yusuf', lastName: 'Abdi', email: 'yusuf.abdi@example.com', discount: 0.1}), + + (amir)-[:BUYS {date: date('2024-10-09')}]->(laptop), + (amir)-[:BUYS {date: date('2025-01-10')}]->(chocolate), + (keisha)-[:BUYS {date: date('2023-07-09')}]->(headphones), + (mateo)-[:BUYS {date: date('2025-03-05')}]->(chocolate), + (mateo)-[:BUYS {date: date('2025-03-05')}]->(coffee), + (mateo)-[:BUYS {date: date('2024-04-11')}]->(laptop), + (hannah)-[:BUYS {date: date('2023-12-11')}]->(coffee), + (hannah)-[:BUYS {date: date('2024-06-02')}]->(headphones), + (leila)-[:BUYS {date: date('2023-05-17')}]->(laptop), + (niko)-[:BUYS {date: date('2025-02-27')}]->(phone), + (niko)-[:BUYS {date: date('2024-08-23')}]->(headphones), + (niko)-[:BUYS {date: date('2024-12-24')}]->(coffee), + (yusuf)-[:BUYS {date: date('2024-12-24')}]->(chocolate), + (yusuf)-[:BUYS {date: date('2025-01-02')}]->(laptop), + + (techCorp)-[:SUPPLIES]->(laptop), + (techCorp)-[:SUPPLIES]->(phone), + (techCorp)-[:SUPPLIES]->(headphones), + (foodies)-[:SUPPLIES]->(chocolate), + (foodies)-[:SUPPLIES]->(coffee) +---- + + +== Composing queries with `NEXT` + +.`NEXT` syntax +[source, cypher] +---- + + +NEXT + + + +NEXT + + +---- + + +=== Passing values to subsequent queries + +In the following example, `NEXT` passes the variable `customer` to the second query: + +.Passing a variable to another query via `NEXT` +==== +.Query +[source, cypher] ---- +MATCH (c:Customer)-[:BUYS]->(:Product {name: 'Chocolate'}) +RETURN c AS customer + +NEXT +RETURN customer.firstName AS chocolateCustomer +---- -[[sequential-syntax]] -== Syntax +.Result +[role="queryresult",options="header,footer",cols="1*(p:Product {name: 'Chocolate'}) +RETURN c AS customer, p AS product + +NEXT + +RETURN customer.firstName AS chocolateCustomer, + product.price * (1 - customer.discount) AS chocolatePrice -.Not allowed: not aliasing returned expressions -[source, cypher, role=test-fail] ---- -WHEN true THEN RETURN 2 -ELSE RETURN 3 + +.Result +[role="queryresult",options="header,footer",cols="2* 2 THEN + RETURN "large number" AS msg +WHEN n.x > 1 THEN + RETURN "small number" AS msg +ELSE + RETURN "tiny number" AS msg + +---- + +.Result +[role="queryresult",options="header,footer",cols="1* Date: Thu, 8 May 2025 14:04:32 +0200 Subject: [PATCH 04/13] updated wording in a few places, revisited queries --- .../composed-queries/sequential-queries.adoc | 156 ++++++++++-------- 1 file changed, 91 insertions(+), 65 deletions(-) diff --git a/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc b/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc index f1ae41199..1331d4931 100644 --- a/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc +++ b/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc @@ -142,20 +142,17 @@ RETURN customer.firstName AS chocolateCustomer, |=== ==== - - [NOTE] ==== -Expressions in a `RETURN` clause must be aliased with an `AS` or a `LET` when they are followed by a `NEXT` clause. +When followed by a `NEXT` clause, expressions in a `RETURN` clause must either be variables that have been introduced before or they must be aliased with `AS`. ==== -// is an example necessary? not a fan of negative examples in general - == Interactions with `CALL` subqueries and `WITH` You can use `NEXT` to rewrite queries containing `CALL` subqueries or a `WITH` clause. +[[call-subquery-rewrite]] .Rewriting a query with a `CALL` subquery ==== [cols="1,1"] @@ -164,46 +161,49 @@ a| .`CALL` subquery [source, cypher] ---- -LET a = 1 -WITH a - -CALL(*) { - LET b = a + 1 - RETURN b - UNION - LET b = a + 2 - RETURN b +MATCH (p:Product) +CALL (p) { + MATCH (c:Customer)-[:BUYS]->(p) + RETURN collect(c.firstName) AS customers } -WITH a, b - -LET c = b + 1 -RETURN a, b, c +RETURN p.name as product, customers ---- a| .`NEXT` [source, cypher] ---- -LET a = 1 -RETURN a +MATCH (p:Product) +RETURN p -NEXT +NEXT -LET b = a + 1 -RETURN a, b -UNION -LET b = a + 2 -RETURN a, b +MATCH (c:Customer)-[:BUYS]->(p) +RETURN collect(c.firstName) AS customers, p -NEXT +NEXT -LET c = b + 1 -RETURN a, b, c +RETURN p.name as product, customers ---- |=== -==== +.Result +[role="queryresult",options="header,footer",cols="2*> has more lines, it is divided into three segments which are easy to read. +It also avoids the parentheses and indentation of the `CALL` subquery. +[[with-rewrite]] .Rewriting a `WITH` query ==== [cols="1,1"] @@ -246,80 +246,106 @@ RETURN d |=== ==== -Variables which are local to a query and which are not explicitly returned are not accessible by its subsequent query in the context of `NEXT`. -This allows you to control variable scope similarly to what you can do with `WITH`, see xref:clauses/with.adoc#variable-scope[Control variables in scope]. + +Variables which are local to a query and which are not explicitly returned are not accessible by subsequent queries in the context of `NEXT`. +This allows you to control variable scope similarly to what you can do with `WITH`, see xref:clauses/with.adoc#variable-scope[Control variables in scope]: in <>, each occurrence of `WITH` is replaced by a `RETURN` and a `NEXT`, preserving the variable scope. [NOTE] ==== `NEXT` cannot be used inside a `CALL` subquery that uses the (deprecated) xref:subqueries/call-subquery.adoc#importing-with[importing `WITH`] syntax. ==== -== Interactions with conditional queries -// use example with the example data set instead +== Interactions with conditional queries +[[next-and-conditional]] .`NEXT` in a conditional query ==== .Query [source, cypher] ---- -MATCH (n) -RETURN n +MATCH (c:Customer)-[:BUYS]->(:Product)<-[:SUPPLIES]-(s:Supplier) +RETURN c.firstName AS customer, s.name AS supplier -NEXT +NEXT -WHEN n.x > 2 THEN - RETURN "large number" AS msg -WHEN n.x > 1 THEN - RETURN "small number" AS msg -ELSE - RETURN "tiny number" AS msg +WHEN supplier = "TechCorp" THEN + RETURN customer, "Tech enjoyer" AS personality +WHEN supplier = "Foodies Inc." THEN + RETURN customer, "Tropical plant enjoyer" AS personality + +NEXT +RETURN customer, collect(DISTINCT personality) AS personalities + +NEXT + +WHEN size(personalities) > 1 THEN + RETURN customer, "Enjoyer of tech and plants" AS personality +ELSE + RETURN customer, personalities[0] AS personality ---- .Result -[role="queryresult",options="header,footer",cols="1*>, customers are assigned personality types based on the products they purchased. +The second query is a conditional query that returns different base personality types for different suppliers the customers purchased from. +The third query aggregates the personality types. +Finally, the fourth query is another conditional query which subsumes multiple base personality types, if present, to a new personality. -== Interactions with `UNION` queries -// use example with the example data set instead +== Interactions with `UNION` queries +[[next-and-union]] .`NEXT` in a query using `UNION` ==== .Query [source, cypher] ---- -RETURN 1 AS a -UNION -RETURN 2 AS a +MATCH (c:Customer)-[:BUYS]->(:Product{name: "Laptop"}) +RETURN c.firstName AS customer +UNION ALL +MATCH (c:Customer)-[:BUYS]-> (:Product{name: "Coffee"}) +RETURN c.firstName AS customer -NEXT +NEXT -RETURN a, a + 1 AS b -UNION -RETURN a, a + 2 AS b +RETURN customer AS customer, count(customer) as numberOfProducts ---- .Result -[role="queryresult",options="header,footer",cols="1*>, the list of customer names from the first query has a duplicate entry for "Mateo" who bought both a laptop and coffee. +The use of `UNION ALL` added him to the list twice. +The second query can access the list, because both parts of the `UNION` return a part of the list, aliased as `customer`. +By using `count()`, the list aggregates the duplicate in the `RETURN` part of the query. \ No newline at end of file From 6f485bc35993a0fab4126de032d83c2883a23d27 Mon Sep 17 00:00:00 2001 From: Richard Sill Date: Thu, 8 May 2025 14:17:34 +0200 Subject: [PATCH 05/13] removed a statement about GQL conformance, changed a heading level --- .../pages/queries/composed-queries/sequential-queries.adoc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc b/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc index 1331d4931..62fbe54c8 100644 --- a/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc +++ b/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc @@ -11,9 +11,6 @@ * `NEXT` can be used instead of xref:subqueries/call-subquery.adoc[] and the xref:clauses/with.adoc[] clause to construct complex queries. * `NEXT` can improve the usability of xref:queries/composed-queries/conditional-queries.adoc[conditional] and xref:queries/composed-queries/combined-queries.adoc[UNION] queries. -`NEXT` was introduced as part of Cypher's xref:appendix/gql-conformance/index.adoc[]. - - [[example-graph]] == Example graph @@ -83,7 +80,7 @@ NEXT ---- -=== Passing values to subsequent queries +== Passing values to subsequent queries In the following example, `NEXT` passes the variable `customer` to the second query: From ee58ed9247ae08f3822c680c8ee4b8d912b35b21 Mon Sep 17 00:00:00 2001 From: Richard Sill <156673635+rsill-neo4j@users.noreply.github.com> Date: Thu, 15 May 2025 15:17:39 +0200 Subject: [PATCH 06/13] Apply suggestions from code review Co-authored-by: JoelBergstrand --- .../gql-conformance/supported-optional.adoc | 6 +-- ...ions-additions-removals-compatibility.adoc | 2 +- .../composed-queries/sequential-queries.adoc | 54 ++----------------- 3 files changed, 7 insertions(+), 55 deletions(-) diff --git a/modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc b/modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc index 7da7eec6b..fb81ed00a 100644 --- a/modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc +++ b/modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc @@ -190,11 +190,9 @@ For example, GQL’s graph reference values `CURRENT_GRAPH` and `CURRENT_PROPERT | Cypher requires using the xref:clauses/with.adoc[`WITH`] clause, which GQL does not. | GQ20 -| `NEXT` statement +| Advanced linear composition with NEXT | xref:queries/composed-queries/sequential-queries.adoc[] -| The GQL standard includes a `YIELD` clause for its `NEXT` statement. -The purpose of this `YIELD` clause is to ensure compatible behavior with SQL as it uses double quotes for delimiting identifiers. -Cypher on the other hand uses double quotes for strings and backticks for quoting and thus having a `YIELD` clause does not provide additional use in Cypher. +| The GQL standard includes a `YIELD` clause for its `NEXT` statement which Cypher does not implement. | GV39 | Temporal types: date, local datetime, and local time support diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index 893cb40cc..337126eef 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -233,7 +233,7 @@ NEXT RETURN 1 AS b ---- -| Introduction of `NEXT` which allows for linear composition of queries into a sequence. +| New `NEXT` keyword used for linear composition of queries. For more information, see xref:queries/composed-queries/sequential-queries.adoc[]. a| diff --git a/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc b/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc index 62fbe54c8..658b3b448 100644 --- a/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc +++ b/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc @@ -145,9 +145,9 @@ When followed by a `NEXT` clause, expressions in a `RETURN` clause must either b ==== -== Interactions with `CALL` subqueries and `WITH` +== Interactions with `CALL` subqueries -You can use `NEXT` to rewrite queries containing `CALL` subqueries or a `WITH` clause. +You can use `NEXT` to rewrite queries containing `CALL` subqueries. [[call-subquery-rewrite]] .Rewriting a query with a `CALL` subquery @@ -200,53 +200,7 @@ RETURN p.name as product, customers Even though the `NEXT` query in <> has more lines, it is divided into three segments which are easy to read. It also avoids the parentheses and indentation of the `CALL` subquery. -[[with-rewrite]] -.Rewriting a `WITH` query -==== -[cols="1,1"] -|=== -a| -.`WITH` -[source, cypher] ----- -LET a = 1 -WITH a -LET b = a + 1 -WITH a, b -LET c = a + b + 1 -WITH b, c -LET d = b + c -RETURN d ----- -a| -.`NEXT` -[source, cypher] ----- -LET a = 1 -RETURN a - -NEXT - -LET b = a + 1 -RETURN a, b - -NEXT - -LET c = a + b + 1 -RETURN b, c - -NEXT - -LET d = b + c -RETURN d ----- -|=== -==== - - -Variables which are local to a query and which are not explicitly returned are not accessible by subsequent queries in the context of `NEXT`. -This allows you to control variable scope similarly to what you can do with `WITH`, see xref:clauses/with.adoc#variable-scope[Control variables in scope]: in <>, each occurrence of `WITH` is replaced by a `RETURN` and a `NEXT`, preserving the variable scope. - +Variables which are local to a query and which are not explicitly returned are not accessible by subsequent queries in the context of `NEXT`. This allows you to control variable scope similarly to what you can do with `WITH`, see xref:clauses/with.adoc#variable-scope[Control variables in scope]. [NOTE] ==== `NEXT` cannot be used inside a `CALL` subquery that uses the (deprecated) xref:subqueries/call-subquery.adoc#importing-with[importing `WITH`] syntax. @@ -256,7 +210,7 @@ This allows you to control variable scope similarly to what you can do with `WIT == Interactions with conditional queries [[next-and-conditional]] -.`NEXT` in a conditional query +. Conditional queries in `NEXT` ==== .Query [source, cypher] From 184f0ee45b2aaa19290108d20374ce569d7b3228 Mon Sep 17 00:00:00 2001 From: Richard Sill <156673635+rsill-neo4j@users.noreply.github.com> Date: Fri, 16 May 2025 11:19:32 +0200 Subject: [PATCH 07/13] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jens Pryce-Åklundh <112686610+JPryce-Aklundh@users.noreply.github.com> --- .../pages/queries/composed-queries/index.adoc | 6 +++--- .../composed-queries/sequential-queries.adoc | 16 ++++++++-------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/modules/ROOT/pages/queries/composed-queries/index.adoc b/modules/ROOT/pages/queries/composed-queries/index.adoc index f234b72b9..fc74dbb97 100644 --- a/modules/ROOT/pages/queries/composed-queries/index.adoc +++ b/modules/ROOT/pages/queries/composed-queries/index.adoc @@ -3,9 +3,9 @@ `UNION`, `WHEN` and `NEXT` enable the composition of multiple separate query branches within a single query. `UNION` allows for combining the results of different queries. -`WHEN` on the other hand enables conditional queries, where different query branches can be made to execute depending on a set of criteria. -Finally, `NEXT` allows for linear composition of queries into a sequence, while making return values from one query available in the next. -As such, `UNION`, `WHEN` and `NEXT` manage in different ways the execution flow and logic of queries and cannot be used in queries as regular clauses. +`WHEN` enables conditional queries, where different query branches can be made to execute depending on a set of criteria. +Finally, `NEXT` allows for the linear composition of sequential queries, passing the return values from one query to the next. +As such, `UNION`, `WHEN`, and `NEXT` manage in different ways the execution flow and logic of queries and cannot be used in queries as regular clauses. For more information, see: diff --git a/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc b/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc index 658b3b448..c256289e6 100644 --- a/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc +++ b/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc @@ -3,13 +3,13 @@ :table-caption!: :page-role: new-2025.06 -`NEXT` allows for linear composition of queries into a sequence of smaller, self-contained segments while making return values from one segment available in the next. +`NEXT` allows for linear composition of queries into a sequence of smaller, self-contained segments, passing the return values from one segment to the next. `NEXT` has the following benefits: * `NEXT` can improve the modularity and readability of complex queries. * `NEXT` can be used instead of xref:subqueries/call-subquery.adoc[] and the xref:clauses/with.adoc[] clause to construct complex queries. -* `NEXT` can improve the usability of xref:queries/composed-queries/conditional-queries.adoc[conditional] and xref:queries/composed-queries/combined-queries.adoc[UNION] queries. +* `NEXT` can improve the usability of xref:queries/composed-queries/conditional-queries.adoc[conditional `WHEN`] and xref:queries/composed-queries/combined-queries.adoc[combined `UNION`] queries. [[example-graph]] @@ -63,7 +63,7 @@ CREATE (techCorp:Supplier {name: 'TechCorp', email: 'contact@techcorp.com'}), ---- -== Composing queries with `NEXT` +== Syntax .`NEXT` syntax [source, cypher] @@ -147,7 +147,7 @@ When followed by a `NEXT` clause, expressions in a `RETURN` clause must either b == Interactions with `CALL` subqueries -You can use `NEXT` to rewrite queries containing `CALL` subqueries. +`NEXT` can serve as a more readable alternative to `CALL` subqueries. [[call-subquery-rewrite]] .Rewriting a query with a `CALL` subquery @@ -197,7 +197,7 @@ RETURN p.name as product, customers |=== ==== -Even though the `NEXT` query in <> has more lines, it is divided into three segments which are easy to read. +Even though the query which uses `NEXT` has more lines, it is divided into three segments which are easy to read. It also avoids the parentheses and indentation of the `CALL` subquery. Variables which are local to a query and which are not explicitly returned are not accessible by subsequent queries in the context of `NEXT`. This allows you to control variable scope similarly to what you can do with `WITH`, see xref:clauses/with.adoc#variable-scope[Control variables in scope]. @@ -254,7 +254,7 @@ ELSE |=== ==== -In <>, customers are assigned personality types based on the products they purchased. +In the query above, customers are assigned personality types based on the products they purchased. The second query is a conditional query that returns different base personality types for different suppliers the customers purchased from. The third query aggregates the personality types. Finally, the fourth query is another conditional query which subsumes multiple base personality types, if present, to a new personality. @@ -296,7 +296,7 @@ RETURN customer AS customer, count(customer) as numberOfProducts |=== ==== -In <>, the list of customer names from the first query has a duplicate entry for "Mateo" who bought both a laptop and coffee. +In this example, the list of customer names from the first query has a duplicate entry for "Mateo" who bought both a laptop and coffee. The use of `UNION ALL` added him to the list twice. The second query can access the list, because both parts of the `UNION` return a part of the list, aliased as `customer`. -By using `count()`, the list aggregates the duplicate in the `RETURN` part of the query. \ No newline at end of file +By using xref:functions/aggregating.adoc#functions-count[`count()`], the list aggregates the duplicate in the `RETURN` part of the query. \ No newline at end of file From 96cb4a7af4b96b30b78249b8442232e45165fbd8 Mon Sep 17 00:00:00 2001 From: Richard Sill Date: Fri, 16 May 2025 16:32:46 +0200 Subject: [PATCH 08/13] review suggestions --- .../composed-queries/sequential-queries.adoc | 37 ++++++------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc b/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc index c256289e6..3019414f4 100644 --- a/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc +++ b/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc @@ -85,8 +85,6 @@ NEXT In the following example, `NEXT` passes the variable `customer` to the second query: .Passing a variable to another query via `NEXT` -==== -.Query [source, cypher] ---- MATCH (c:Customer)-[:BUYS]->(:Product {name: 'Chocolate'}) @@ -108,12 +106,9 @@ RETURN customer.firstName AS chocolateCustomer 1+d|Rows: 3 |=== -==== .Passing multiple variables to another query via `NEXT` -==== -.Query [source, cypher] ---- MATCH (c:Customer)-[:BUYS]->(p:Product {name: 'Chocolate'}) @@ -137,25 +132,23 @@ RETURN customer.firstName AS chocolateCustomer, 2+d|Rows: 3 |=== -==== [NOTE] ==== When followed by a `NEXT` clause, expressions in a `RETURN` clause must either be variables that have been introduced before or they must be aliased with `AS`. ==== +Variables which are local to a query and which are not explicitly returned are not accessible by subsequent queries in the context of `NEXT`. This allows you to control variable scope similarly to what you can do with `WITH`, see xref:clauses/with.adoc#variable-scope[Control variables in scope]. + == Interactions with `CALL` subqueries `NEXT` can serve as a more readable alternative to `CALL` subqueries. -[[call-subquery-rewrite]] -.Rewriting a query with a `CALL` subquery +[.tabbed-example] ==== -[cols="1,1"] -|=== -a| -.`CALL` subquery +[.include-with-CALL-subquery] +====== [source, cypher] ---- MATCH (p:Product) @@ -165,8 +158,9 @@ CALL (p) { } RETURN p.name as product, customers ---- -a| -.`NEXT` +====== +[.include-with-NEXT] +====== [source, cypher] ---- MATCH (p:Product) @@ -181,7 +175,8 @@ NEXT RETURN p.name as product, customers ---- -|=== +====== +==== .Result [role="queryresult",options="header,footer",cols="2*(:Product)<-[:SUPPLIES]-(s:Supplier) @@ -252,7 +242,6 @@ ELSE 2+d|Rows: 7 |=== -==== In the query above, customers are assigned personality types based on the products they purchased. The second query is a conditional query that returns different base personality types for different suppliers the customers purchased from. @@ -262,10 +251,7 @@ Finally, the fourth query is another conditional query which subsumes multiple b == Interactions with `UNION` queries -[[next-and-union]] .`NEXT` in a query using `UNION` -==== -.Query [source, cypher] ---- MATCH (c:Customer)-[:BUYS]->(:Product{name: "Laptop"}) @@ -294,7 +280,6 @@ RETURN customer AS customer, count(customer) as numberOfProducts 2+d|Rows: 6 |=== -==== In this example, the list of customer names from the first query has a duplicate entry for "Mateo" who bought both a laptop and coffee. The use of `UNION ALL` added him to the list twice. From 8289a5bfaf2b899bd3d0f63ee4983d896ff52b3f Mon Sep 17 00:00:00 2001 From: Richard Sill Date: Wed, 21 May 2025 14:05:59 +0200 Subject: [PATCH 09/13] added sections to address {} braces for NEXT inside UNION and conditional queries --- .../composed-queries/sequential-queries.adoc | 81 ++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc b/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc index 3019414f4..96fd1ca4a 100644 --- a/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc +++ b/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc @@ -249,6 +249,49 @@ The third query aggregates the personality types. Finally, the fourth query is another conditional query which subsumes multiple base personality types, if present, to a new personality. +=== Using `NEXT` inside a conditional query using `{}` + +In a conditional query that that has a `NEXT` in any of its `THEN` blocks or the `ELSE` block, wrap the part after `THEN` or `ELSE` with `{}`. + +.`NEXT` inside a conditional query +[source, cypher] +---- +MATCH (c:Customer)-[:BUYS]->(p:Product) +RETURN c AS customer, sum(p.price) AS sum + +NEXT + +WHEN sum >= 1000 THEN { + RETURN customer.firstName AS customer, "club 1000 plus" AS customerType, sum AS sum +} +ELSE { + RETURN customer AS customer, sum * (1 - customer.discount) AS finalSum + + NEXT + + RETURN customer.firstName AS customer, "club below 1000" AS customerType, finalSum AS sum +} +---- + +.Result +[role="queryresult",options="header,footer",cols="3* Date: Wed, 21 May 2025 14:53:35 +0200 Subject: [PATCH 10/13] made it clearer that the {} braces are necessary, replaced an example with a different one that uses the example data set --- .../composed-queries/sequential-queries.adoc | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc b/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc index 96fd1ca4a..141fadbcb 100644 --- a/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc +++ b/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc @@ -251,7 +251,7 @@ Finally, the fourth query is another conditional query which subsumes multiple b === Using `NEXT` inside a conditional query using `{}` -In a conditional query that that has a `NEXT` in any of its `THEN` blocks or the `ELSE` block, wrap the part after `THEN` or `ELSE` with `{}`. +In a conditional query that that has a `NEXT` in any of its `THEN` blocks or the `ELSE` block, it is necessary to wrap the part after `THEN` or `ELSE` with `{}`. .`NEXT` inside a conditional query [source, cypher] @@ -332,35 +332,43 @@ By using xref:functions/aggregating.adoc#functions-count[`count()`], the list ag === Using `NEXT` inside a `UNION` using `{}` -In a `UNION` query that that has a `NEXT` in any of its blocks, wrap that block with `{}`. +In a `UNION` query that that has a `NEXT` in any of its blocks, it is necessary to wrap that block with `{}`. .`NEXT` inside `UNION` [source, cypher] ---- { - RETURN 1 AS a +MATCH (c:Customer)-[:BUYS]->(:Product {name: 'Chocolate'}) +RETURN c AS customer - NEXT +NEXT - RETURN a + 1 AS b +RETURN customer.firstName AS plantCustomer } + UNION ALL + { - RETURN 1 AS a +MATCH (c:Customer)-[:BUYS]->(:Product {name: 'Coffee'}) +RETURN c AS customer - NEXT +NEXT - RETURN a + 1 AS b +RETURN customer.firstName AS plantCustomer } ---- .Result [role="queryresult",options="header,footer",cols="1* Date: Wed, 21 May 2025 16:35:22 +0200 Subject: [PATCH 11/13] review suggestion --- .../pages/queries/composed-queries/sequential-queries.adoc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc b/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc index 141fadbcb..402ed8b5a 100644 --- a/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc +++ b/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc @@ -135,7 +135,9 @@ RETURN customer.firstName AS chocolateCustomer, [NOTE] ==== -When followed by a `NEXT` clause, expressions in a `RETURN` clause must either be variables that have been introduced before or they must be aliased with `AS`. +When followed by `NEXT`, a `RETURN` clause may only contain variables or aliased expressions. +Literals or unaliased expressions are not allowed. +For example, `RETURN 1` and `RETURN 1 + 1` cannot precede `NEXT`, but `RETURN 1 AS one` and `RETURN 1 + 1 AS two` can." ==== Variables which are local to a query and which are not explicitly returned are not accessible by subsequent queries in the context of `NEXT`. This allows you to control variable scope similarly to what you can do with `WITH`, see xref:clauses/with.adoc#variable-scope[Control variables in scope]. From dba5330b636ecae53e6ef237ec6f53f8e3eb48e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Thu, 5 Jun 2025 14:59:57 +0200 Subject: [PATCH 12/13] small editorial --- .../composed-queries/sequential-queries.adoc | 39 +++++++++---------- modules/ROOT/pages/syntax/keywords.adoc | 1 + 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc b/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc index 402ed8b5a..a6c72bad6 100644 --- a/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc +++ b/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc @@ -11,7 +11,6 @@ * `NEXT` can be used instead of xref:subqueries/call-subquery.adoc[] and the xref:clauses/with.adoc[] clause to construct complex queries. * `NEXT` can improve the usability of xref:queries/composed-queries/conditional-queries.adoc[conditional `WHEN`] and xref:queries/composed-queries/combined-queries.adoc[combined `UNION`] queries. - [[example-graph]] == Example graph @@ -62,7 +61,7 @@ CREATE (techCorp:Supplier {name: 'TechCorp', email: 'contact@techcorp.com'}), (foodies)-[:SUPPLIES]->(coffee) ---- - +[[syntax]] == Syntax .`NEXT` syntax @@ -79,7 +78,7 @@ NEXT ---- - +[[passing-values]] == Passing values to subsequent queries In the following example, `NEXT` passes the variable `customer` to the second query: @@ -87,12 +86,13 @@ In the following example, `NEXT` passes the variable `customer` to the second qu .Passing a variable to another query via `NEXT` [source, cypher] ---- -MATCH (c:Customer)-[:BUYS]->(:Product {name: 'Chocolate'}) -RETURN c AS customer +MATCH (c:Customer) +RETURN c AS customer -NEXT +NEXT -RETURN customer.firstName AS chocolateCustomer +MATCH (customer)-[:BUYS]->(:Product {name: 'Chocolate'}) +RETURN customer.firstName AS chocolateCustomer ---- .Result @@ -118,7 +118,6 @@ NEXT RETURN customer.firstName AS chocolateCustomer, product.price * (1 - customer.discount) AS chocolatePrice - ---- .Result @@ -137,12 +136,12 @@ RETURN customer.firstName AS chocolateCustomer, ==== When followed by `NEXT`, a `RETURN` clause may only contain variables or aliased expressions. Literals or unaliased expressions are not allowed. -For example, `RETURN 1` and `RETURN 1 + 1` cannot precede `NEXT`, but `RETURN 1 AS one` and `RETURN 1 + 1 AS two` can." +For example, `RETURN 1` and `RETURN 1 + 1` cannot precede `NEXT`, but `RETURN 1 AS one` and `RETURN 1 + 1 AS two` can. ==== Variables which are local to a query and which are not explicitly returned are not accessible by subsequent queries in the context of `NEXT`. This allows you to control variable scope similarly to what you can do with `WITH`, see xref:clauses/with.adoc#variable-scope[Control variables in scope]. - +[[next-and-call]] == Interactions with `CALL` subqueries `NEXT` can serve as a more readable alternative to `CALL` subqueries. @@ -201,7 +200,7 @@ It also avoids the parentheses and indentation of the `CALL` subquery. `NEXT` cannot be used inside a `CALL` subquery that uses the (deprecated) xref:subqueries/call-subquery.adoc#importing-with[importing `WITH`] syntax. ==== - +[[next-and-conditional-queries]] == Interactions with conditional queries .Conditional queries in `NEXT` @@ -246,14 +245,14 @@ ELSE |=== In the query above, customers are assigned personality types based on the products they purchased. -The second query is a conditional query that returns different base personality types for different suppliers the customers purchased from. -The third query aggregates the personality types. -Finally, the fourth query is another conditional query which subsumes multiple base personality types, if present, to a new personality. - +The second segment is a conditional query that returns different base personality types for different suppliers the customers purchased from. +The third segment aggregates the personality types. +Finally, the fourth segment is another conditional query which subsumes multiple base personality types, if present, to a new personality. +[[next-conditional-queries-top-level-braces]] === Using `NEXT` inside a conditional query using `{}` -In a conditional query that that has a `NEXT` in any of its `THEN` blocks or the `ELSE` block, it is necessary to wrap the part after `THEN` or `ELSE` with `{}`. +If a conditional query has a `NEXT` in any of its `THEN` or `ELSE` blocks, it is necessary to wrap the part after `THEN` or `ELSE` with `{}`. .`NEXT` inside a conditional query [source, cypher] @@ -293,7 +292,7 @@ ELSE { The query above calculates the total price of products purchased per customer and then only applies the customer discount to sums below 1000. - +[[next-and-union]] == Interactions with `UNION` queries .`NEXT` in a query using `UNION` @@ -326,15 +325,15 @@ RETURN customer AS customer, count(customer) as numberOfProducts 2+d|Rows: 6 |=== -In this example, the list of customer names from the first query has a duplicate entry for "Mateo" who bought both a laptop and coffee. +In this example, the list of customer names from the first segment has a duplicate entry for "Mateo" who bought both a laptop and coffee. The use of `UNION ALL` added him to the list twice. -The second query can access the list, because both parts of the `UNION` return a part of the list, aliased as `customer`. +The second segment can access the list, because both parts of the `UNION` return a part of the list, aliased as `customer`. By using xref:functions/aggregating.adoc#functions-count[`count()`], the list aggregates the duplicate in the `RETURN` part of the query. === Using `NEXT` inside a `UNION` using `{}` -In a `UNION` query that that has a `NEXT` in any of its blocks, it is necessary to wrap that block with `{}`. +If a `UNION` query has a `NEXT` in any of its blocks, it is necessary to wrap that block with `{}`. .`NEXT` inside `UNION` [source, cypher] diff --git a/modules/ROOT/pages/syntax/keywords.adoc b/modules/ROOT/pages/syntax/keywords.adoc index 792c0160a..60efbf5a2 100644 --- a/modules/ROOT/pages/syntax/keywords.adoc +++ b/modules/ROOT/pages/syntax/keywords.adoc @@ -235,6 +235,7 @@ Note that with future functionality, Cypher may be extended with additional keyw * `NAMES` * `NAN` * `NEW` +* `NEXT` * `NFC` * `NFD` * `NFKC` From 49741fbdbdb09b208ba62b5e2962bbdda19b0317 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Thu, 5 Jun 2025 15:05:15 +0200 Subject: [PATCH 13/13] remove double Using --- .../pages/queries/composed-queries/sequential-queries.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc b/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc index a6c72bad6..29c84b486 100644 --- a/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc +++ b/modules/ROOT/pages/queries/composed-queries/sequential-queries.adoc @@ -250,7 +250,7 @@ The third segment aggregates the personality types. Finally, the fourth segment is another conditional query which subsumes multiple base personality types, if present, to a new personality. [[next-conditional-queries-top-level-braces]] -=== Using `NEXT` inside a conditional query using `{}` +=== `NEXT` inside a conditional query using `{}` If a conditional query has a `NEXT` in any of its `THEN` or `ELSE` blocks, it is necessary to wrap the part after `THEN` or `ELSE` with `{}`. @@ -331,7 +331,7 @@ The second segment can access the list, because both parts of the `UNION` return By using xref:functions/aggregating.adoc#functions-count[`count()`], the list aggregates the duplicate in the `RETURN` part of the query. -=== Using `NEXT` inside a `UNION` using `{}` +=== `NEXT` inside a `UNION` using `{}` If a `UNION` query has a `NEXT` in any of its blocks, it is necessary to wrap that block with `{}`.