Migration to Cypher Builder 3

This guide details all the changes needed to migrate from Cypher® Builder version 2 to version 3.

If you must support Neo4j 4, stay with Cypher Builder 2.x, otherwise, migrate to version 3.

Compatibility changes

Moved to ES modules

Cypher Builder has been migrated to ES modules, and is no longer available as a CommonJS module.

Minimum node engine changed to 20.0.0

Node.js 16 is no longer supported. Update Node.js to version 20.0.0 or above.

If you are using CommonJS in your project ensure you are using at least Node.js version 20.19.0.

Cypher 4 no longer supported

Cypher 4, and Neo4j 4 databases are no longer supported. Cypher Builder 3 targets Cypher 5 and 25.

The following features are Cypher 4 only, and have been removed from Cypher Builder.

Removed functions deprecated in Cypher 5

The following functions are still supported in Cypher 5, but have been deprecated. These been removed from Cypher Builder:

  • distance in favor of point.distance

  • id in favor of elementId

Removed support for patterns in size

No longer supported:

Cypher.size(new Cypher.Pattern(node));
size((this0));

Instead, use Cypher.Count:

new Cypher.Count(new Cypher.Pattern(node));
COUNT {
    (this0)
}

Removed labelOperator

Removed the option labelOperator from the .build method. The operator & is now the default operator when using multiple labels:

No longer supported:

const { cypher, params } = matchQuery.build({
    labelOperator: "&",
});

Before:

MATCH (this1:Movie:Film)

After:

MATCH (this1:Movie&Film)

The label operator : is no longer supported.

Removed .importWith from Call

Remove .importWith from Call clauses in favor of constructor parameters.

No longer supported:

const clause = new Cypher.Call(nestedClause).importWith(movieNode, actorNode);
CALL {
    WITH var0, var1
    // Nested clause
}

After:

const clause = new Cypher.Call(nestedClause, [movieNode, actorNode]);
CALL (var0, var1){
    // Nested clause
}

Removed support for APOC

No APOC functions or procedures are supported in Cypher Builder 3. The following are no longer available:

  • apoc.util.validate

  • apoc.util.validatePredicate

  • apoc.date.convertFormat

  • apoc.cypher.runFirstColumnMany

  • apoc.cypher.runFirstColumnSingle

To use APOC methods, create a custom function or procedure. For example:

function validate(
    predicate: Cypher.Predicate,
    message: string,
    params: Cypher.List | Cypher.Literal | Cypher.Map
): Cypher.VoidProcedure {
    return new Cypher.VoidProcedure(
        "apoc.util.validate",
        [predicate,  new Cypher.Literal(message), params]
    );
}
function validatePredicate(predicate: Cypher.Predicate, message: string): Cypher.Function {
    return new Cypher.Function("
        apoc.util.validatePredicate",
        [predicate, new Cypher.Literal(message), new Cypher.Literal([0])]
    );
}

API changes

The following are changes made to improve consistency across the Cypher Builder API.

ListComprehension

Removed the second parameter of the constructor

The second parameter of the ListComprehension constructor has been removed in favor of .in.

Before:

new Cypher.ListComprehension(variable, new Cypher.Literal([1, 2]));

After:

new Cypher.ListComprehension(variable).in(new Cypher.Literal([1, 2]));

In both cases, the same comprehension is generated:

[var0 IN [1, 2]]

The ListComprehension method .in no longer throws if called twice

The ListComprehension method .in no longer throws if called twice. Instead, it overrides the expression.

Before, the following code will throw an error:

new Cypher.ListComprehension(variable).in(new Cypher.Literal([1, 2])).in(new Cypher.Literal([1]))

After, it will generate the following Cypher:

[var0 IN [1]]

Note that the same Cypher is generated if you omit the first .in:

new Cypher.ListComprehension(variable).in(new Cypher.Literal([1]))

Foreach

Removed extra parameters in the Cypher.Foreach constructor

The extra parameters in the Cypher.Foreach constructor have been removed in favor of the methods in and do.

For example, to create the following Cypher:

FOREACH (var0 IN [1, 2, 3] |
        CREATE (this1:Movie)
        SET
            this1.id = var0
    )

Before:

const list = new Cypher.Literal([1, 2, 3]);
const variable = new Cypher.Variable();

const movieNode = new Cypher.Node();
const createMovie = new Cypher.Create(new Cypher.Pattern(movieNode, { labels: ["Movie"] })).set([
    movieNode.property("id"),
    variable,
]);

const foreachClause = new Cypher.Foreach(variable, list, createMovie);

After:

const list = new Cypher.Literal([1, 2, 3]);
const variable = new Cypher.Variable();

const movieNode = new Cypher.Node();
const createMovie = new Cypher.Create(new Cypher.Pattern(movieNode, { labels: ["Movie"] })).set([
    movieNode.property("id"),
    variable,
]);

const foreachClause = new Cypher.Foreach(variable).in(list).do(createMovie);

Other breaking changes

Removed method .children from concat clauses

const query = Cypher.utils.concat(clause1, clause2);
query.children; // No longer supported

Removed type Operation

The type Cypher.Operation is no longer available, use Cypher.Expr instead:

Before:

const myOperation: Cypher.Operation = Cypher.and()

After:

const myOperation: Cypher.Expr = Cypher.and()

Other changes

Changed Cypher formatting

Generated Cypher has been changed to better follow the best practices recommended by the Cypher Styleguide.

For example:

Before:

CALL {
    CREATE (this0:Movie)
    SET
        this0.id = "The Matrix"
    RETURN this0
}
RETURN this0

After:

CALL {
  CREATE (this0:Movie)
  SET this0.id = 'The Matrix'
  RETURN this0
}
RETURN this0

This doesn’t have any impact on the behavior itself, and should not cause any breaking changes. It may however affect projects that modify or test the exact output of the Cypher generated with Cypher Builder.