Skip to content

Commit 1598a77

Browse files
authored
Merge pull request #556 from neo4j/call-docs
Improve docs on call subqueries
2 parents 32ab1a4 + 9d1067e commit 1598a77

File tree

5 files changed

+139
-28
lines changed

5 files changed

+139
-28
lines changed

docs/modules/ROOT/pages/getting-started/relationships-and-advanced-filtering.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ It also adds the property `roles` from the relationship to the projection, alias
1919
Querying it on the Movies Dataset should prompt this result:
2020

2121
.Result
22-
[role="queryresult",options="header,footer",cols="4*<m"]
22+
[role="queryresult",options="header",cols="4*<m"]
2323
|===
2424
| m.title | m.tagline | m.released | actingRoles
2525
| "The Matrix" | "Welcome to the Real World" | 1999 | ["Neo"]

docs/modules/ROOT/pages/index.adoc

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,30 @@
44

55
Cypher Builder is a programmatic API for building link:https://neo4j.com/docs/cypher-manual/[Cypher] queries for Neo4j in JavaScript and TypeScript.
66

7+
For example, the following code:
8+
9+
[source, javascript]
10+
----
11+
const movieNode = new Cypher.Node();
12+
const pattern = new Cypher.Pattern(movieNode, { labels: ["Movie"] });
13+
14+
const matchQuery = new Cypher.Match(pattern)
15+
.where(movieNode, {
16+
title: new Cypher.Param("The Matrix"),
17+
})
18+
.return(movieNode.property("title"));
19+
----
20+
21+
Generates the following Cypher query:
22+
23+
[source, cypher]
24+
----
25+
MATCH (this0:Movie)
26+
WHERE this0.title = $param0
27+
RETURN this0.title
28+
----
29+
30+
731

832

933
If you are using Java, check link:https://neo4j.github.io/cypher-dsl[Neo4j Cypher-DSL].

docs/modules/ROOT/pages/subqueries/call.adoc

Lines changed: 112 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,30 @@
22
:description: This page describes how to create CALL subqueries with the Cypher Builder.
33
= `Call`
44

5-
Cypher link:https://neo4j.com/docs/cypher-manual/current/subqueries/call-subquery/[`CALL` subqueries] can be created with `new Cypher.Call()` in Cypher Builder.
6-
To do this, a valid query needs to be passed to `Call`, for example:
5+
`Cypher.Call` generates Cypher link:https://neo4j.com/docs/cypher-manual/current/subqueries/call-subquery/[`CALL` subqueries]. To do this, instantiate `Cypher.Call` with a valid subquery as parameter in the constructor.
6+
7+
[source, javascript]
8+
----
9+
new Cypher.Call(subquery);
10+
----
11+
12+
In the following example, `Cypher.Call` receives a `Cypher.Match` clause.
713

814
[source, javascript]
915
----
1016
const dog = new Cypher.Node({ labels: ["Dog"] });
1117
const person = new Cypher.Node({ labels: ["Person"] });
18+
const dogName = new Cypher.NamedVariable("dogName");
1219
13-
const dogName = new Cypher.NamedVariable("dogName")
20+
const pattern = new Cypher.Pattern(person).related(new Cypher.Relationship({ type: "HAS_DOG" })).to(dog)
21+
const subquery = new Cypher.Match(pattern).return([dog.property("name"), dogName]);
1422
15-
const subquery = new Cypher.Match(
16-
new Cypher.Pattern(person).related(new Cypher.Relationship({ type: "HAS_DOG" })).to(dog)
17-
).return([dog.property("name"), dogName]);
18-
19-
const classClause = new Cypher.Call(subquery).return(dogName);
23+
const callClause = new Cypher.Call(subquery).return(dogName);
24+
const { cypher, params } = callClause.build();
2025
----
2126

27+
This example builds a `CALL` clause with the `MATCH` subquery inside.
28+
2229
[source, cypher]
2330
----
2431
CALL {
@@ -30,20 +37,29 @@ RETURN dogName
3037

3138
== Variable scope
3239

33-
The variable scope can be set with the second parameter of `new Cypher.Call()`, by passing an array of variables:
40+
xref:../variables-and-params/variables.adoc[Variables] can be added to the `CALL` scope by passing the to the second parameter of the constructor, as an array. These variables will be available within the scope of the subquery in the generated Cypher.
41+
42+
[source, javascript]
43+
----
44+
new Cypher.Call(subquery, [var1, var2]);
45+
----
46+
47+
The following code will make two node variables available in the `CREATE` statement inside `CALL`.
3448

3549
[source, javascript]
3650
----
3751
const movieNode = new Cypher.Node();
3852
const actorNode = new Cypher.Node();
3953
40-
const clause = new Cypher.Call(new Cypher.Create(new Cypher.Pattern(movieNode).related().to(actorNode)), [
54+
const createSubquery = new Cypher.Create(new Cypher.Pattern(movieNode).related().to(actorNode));
55+
56+
const clause = new Cypher.Call(createSubquery, [
4157
movieNode,
4258
actorNode,
4359
]);
4460
----
4561

46-
This will add the two variables `movieNode` and `actorNode` to the `CALL` scope:
62+
The resulting Cypher adds the two variables `movieNode` (`this0`) and `actorNode` (`this1`) to the `CALL` scope:
4763

4864
[source, cypher]
4965
----
@@ -52,14 +68,16 @@ CALL (this0, this1) {
5268
}
5369
----
5470

55-
To import all variables from the outer scope, the second parameter can be set to the string `"*"`:
71+
To import all variables from the outer scope, set the second parameter to the string `"*"`:
5672

5773
[source, javascript]
5874
----
5975
const movieNode = new Cypher.Node();
6076
const actorNode = new Cypher.Node();
6177
62-
const clause = new Cypher.Call(new Cypher.Create(new Cypher.Pattern(movieNode).related().to(actorNode)), "*");
78+
const createSubquery = new Cypher.Create(new Cypher.Pattern(movieNode).related().to(actorNode));
79+
80+
const clause = new Cypher.Call(createSubquery, "*");
6381
----
6482

6583
[source, cypher]
@@ -74,12 +92,12 @@ CALL (*) {
7492

7593
[WARNING]
7694
====
77-
This method is deprecated in favor of <<_variable_scope>>
95+
This method is deprecated in favor of <<_variable_scope>>.
7896
====
7997

8098
[WARNING]
8199
====
82-
Import with cannot be used if scope variables are defined and will throw an error.
100+
`ImportWith` cannot be used if scope variables are defined and will throw an error.
83101
====
84102

85103

@@ -115,11 +133,11 @@ Note how the previous example uses `.concat` to concatenate the first `MATCH` st
115133

116134
== `.inTransactions`
117135

118-
A `CALL` subquery can be executed in separate transactions by using the `inTransaction` method:
136+
The method `.inTransactions` appends the modifier `IN TRANSACTIONS` at the end of the `CALL` subquery, this way subqueries will link:https://neo4j.com/docs/cypher-manual/current/subqueries/subqueries-in-transactions/[execute in separate transactions]:
119137

120138
[source, javascript]
121139
----
122-
new Cypher.Match(node).call(deleteSubquery).inTransactions();
140+
new Call(subquery).inTransactions();
123141
----
124142

125143
[source, cypher]
@@ -129,30 +147,98 @@ CALL {
129147
} IN TRANSACTIONS
130148
----
131149

132-
The method `inTransaction` accepts an object with the following options:
150+
The method `inTransactions` accepts multiple settings to change the behaviour of the transactions, such as, error handling, rows per transaction, or concurrency. You can pass one or more settings, as an object, to `.inTransaction`.
151+
152+
[source, javascript]
153+
----
154+
new Call(subquery).inTransactions({
155+
ofRows: 10
156+
});
157+
----
158+
159+
`inTransactions` supports the following settings:
160+
161+
[cols="1,1,1",options="header"]
162+
|===
163+
| Setting | Description | Cypher
164+
| `ofRows` | Define the number of rows per transaction | link:https://neo4j.com/docs/cypher-manual/current/subqueries/subqueries-in-transactions/#batching[`IN TRANSACTIONS OF [n\] ROWS`]
165+
| `onError` | Error handling behaviour, can be `continue`, `break` or `fail` | link:https://neo4j.com/docs/cypher-manual/current/subqueries/subqueries-in-transactions/#error-behavior[`ON ERROR [CONTINUE \| BREAK \| FAIL\]`]
166+
| `concurrentTransactions` | The maximum number of transactions to execute concurrently | link:https://neo4j.com/docs/cypher-manual/current/subqueries/subqueries-in-transactions/#concurrent-transactions[`IN [n\] CONCURRENT TRANSACTIONS`]
167+
| `retry` | If set to `true`, retries failing transactions. Can be a number to define the maximum duration, in seconds. | link:https://neo4j.com/docs/cypher-manual/current/subqueries/subqueries-in-transactions/#on-error-retry[`ON ERROR RETRY [FOR x SECONDS\]`]
168+
|===
169+
170+
171+
**Example 1: Concurrent transaction of rows**
172+
173+
[source, javascript]
174+
----
175+
const clause = new Cypher.Call(subquery).inTransactions({
176+
ofRows: 10,
177+
concurrentTransactions: 5
178+
});
179+
----
180+
181+
182+
[source, cypher]
183+
----
184+
CALL {
185+
// subquery
186+
} IN 5 CONCURRENT TRANSACTIONS OF 10 ROWS
187+
----
188+
189+
**Example 2: Retry with maximum duration**
190+
191+
[source, javascript]
192+
----
193+
const clause = new Cypher.Call(subquery).inTransactions({
194+
retry: 10
195+
});
196+
----
197+
198+
199+
[source, cypher]
200+
----
201+
CALL {
202+
// subquery
203+
} TRANSACTIONS ON ERROR RETRY FOR 10 SECONDS
204+
----
205+
206+
**Example 3: Retry error fallback**
207+
208+
[source, javascript]
209+
----
210+
const clause = new Cypher.Call(subquery).inTransactions({
211+
retry: true,
212+
onError: "continue"
213+
});
214+
----
215+
216+
217+
[source, cypher]
218+
----
219+
CALL {
220+
// subquery
221+
} TRANSACTIONS ON ERROR RETRY THEN CONTINUE
222+
----
133223

134-
* `ofRows`: A number to define the batch of rows. Translates to `IN TRANSACTIONS OF 10 ROWS`.
135-
* `onError`: A behavior for error handling. This can be `continue`, `break` or `fail`. Translates to `ON ERROR CONTINUE`.
136-
* `concurrentTransactions`: A number to execute concurrent transactions. Translates to `IN x CONCURRENT TRANSACTIONS`.
137-
* `retry`: Either a boolean or a number. Translates to `ON ERROR RETRY [FOR x SECONDS]`. If `onError` is also defined, it will add `THEN [error]`.
138224

139225
== Optional Call
140226

141-
A `CALL` subquery can be converted to an `OPTIONAL CALL` by using the `.optional` method:
227+
The method `.optional()` transforms a `CALL` subquery into link:https://neo4j.com/docs/cypher-manual/current/subqueries/call-subquery/#optional-call[`OPTIONAL CALL`] subquery.
142228

143229
[source, javascript]
144230
----
145-
new Cypher.Call(deleteSubquery).optional();
231+
new Cypher.Call(subquery).optional();
146232
----
147233

148-
Alternatively, the clause `OptionalCall` can be used to create an `OPTIONAL CALL` directly:
234+
Alternatively, the clause `OptionalCall` creates an `OPTIONAL CALL` directly:
149235

150236
[source, javascript]
151237
----
152238
new Cypher.OptionalCall(deleteSubquery);
153239
----
154240

155-
Both will generate the Cypher:
241+
Both generate the Cypher:
156242

157243
[source, cypher]
158244
----

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
"jest-extended": "^6.0.0",
5959
"prettier": "^3.4.1",
6060
"ts-jest": "^29.2.5",
61-
"typedoc": "^0.28.7",
61+
"typedoc": "^0.28.8",
6262
"typescript": "^5.6.3"
6363
}
6464
}

src/clauses/Call.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ export class Call extends Clause {
204204
/**
205205
* @see {@link https://neo4j.com/docs/cypher-manual/current/subqueries/call-subquery/#optional-call | Cypher Documentation}
206206
* @group Subqueries
207+
* @since Neo4j 5.24
207208
*/
208209
export class OptionalCall extends Call {
209210
constructor(subquery: Clause, variableScope?: Variable[] | "*") {

0 commit comments

Comments
 (0)