Call

Cypher® CALL subqueries can be created with new Cypher.Call() in Cypher Builder. To do this, a valid query needs to be passed to Call, for example:

const dog = new Cypher.Node({ labels: ["Dog"] });
const person = new Cypher.Node({ labels: ["Person"] });

const dogName = new Cypher.NamedVariable("dogName")

const subquery = new Cypher.Match(
    new Cypher.Pattern(person).related(new Cypher.Relationship({ type: "HAS_DOG" })).to(dog)
).return([dog.property("name"), dogName]);

const classClause = new Cypher.Call(subquery).return(dogName);
CALL {
    MATCH (this0:Person)-[this1:HAS_DOG]->(this2:Dog)
    RETURN this2.name AS dogName
}
RETURN dogName

Variable scope

The variable scope can be set with the second parameter of new Cypher.Call(), by passing an array of variables:

const movieNode = new Cypher.Node();
const actorNode = new Cypher.Node();

const clause = new Cypher.Call(new Cypher.Create(new Cypher.Pattern(movieNode).related().to(actorNode)), [
    movieNode,
    actorNode,
]);

This will add the two variables movieNode and actorNode to the CALL scope:

CALL (this0, this1) {
    CREATE (this0)-[this2]->(this1)
}

To import all variables from the outer scope, the second parameter can be set to the string "*":

const movieNode = new Cypher.Node();
const actorNode = new Cypher.Node();

const clause = new Cypher.Call(new Cypher.Create(new Cypher.Pattern(movieNode).related().to(actorNode)), "*");
CALL (*) {
    CREATE (this0)-[this2]->(this1)
}

.importWith

Import with cannot be used if scope variables are defined and will throw an error

To add variables to a CALL subquery context, you need to add a WITH statement. This can be achieved by using the .importWith method:

const dog = new Cypher.Node();
const person = new Cypher.Node();

const dogName = new Cypher.NamedVariable("dogName");

const subquery = new Cypher.Match(
    new Cypher.Pattern(person, {labels: ["Person"]}).related(new Cypher.Relationship({ type: "HAS_DOG" })).to(dog, {labels: ["Dog"]})
).return([dog.property("name"), dogName]);

const clause = new Cypher.Match(new Cypher.Pattern(person, {labels: ["Person"]})).call(subquery).importWith(person).return(dogName);
MATCH (this0:Person)
CALL {
    WITH this0
    MATCH (this0:Person)-[this1:HAS_DOG]->(this2:Dog)
    RETURN this2.name AS dogName
}
RETURN dogName

Note how the previous example uses .concat to concatenate the first MATCH statement and the CALL clause.

.inTransactions

A CALL subquery can be executed in separate transactions by using the inTransaction method:

new Cypher.Match(node).call(deleteSubquery).inTransactions();
CALL {
    // Subquery
} IN TRANSACTIONS

The method inTransaction accepts an object with the following options:

  • ofRows: A number to define the batch of rows. Translates to IN TRANSACTIONS OF 10 ROWS.

  • onError: A behavior for error handling. This can be continue, break or fail. Translates to ON ERROR CONTINUE.

  • concurrentTransactions: A number to execute concurrent transactions. Translates to IN x CONCURRENT TRANSACTIONS.

  • 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].

Optional Call

A CALL subquery can be converted to an OPTIONAL CALL by using the .optional method:

new Cypher.Call(deleteSubquery).optional();

Alternatively, the clause OptionalCall can be used to create an OPTIONAL CALL directly:

new Cypher.OptionalCall(deleteSubquery);

Both will generate the Cypher:

OPTIONAL CALL {
    // Subquery
}