Cypher coverage

This is the public preview documentation of Neo4j Virtual Graph. To provide feedback, please use the feedback form you were granted access to.

During the public preview, we advise you not to use sensitive or production data with Virtual Graph.

Virtual Graph provides a subset of the Cypher® query language.

Queries against virtual graphs are partially interpreted directly in Cypher and partially handed to the underlying SQL. The interpretation also depends on the SQL implementation used.

Expect deviations from the Cypher standard when using Virtual Graph. Also note that Virtual Graph’s Cypher coverage is subject to change as it is actively being developed.

The Cypher coverage on this page apply to both the Aura and the self-managed version of Neo4j Virtual Graph.

Check for Virtual Graph databases

Virtual Graph databases are read-only, and SHOW DATABASES reports them with type = "virtual graph":

SHOW DATABASES
SHOW DATABASES YIELD name, type, access, currentStatus
  WHERE type = 'virtual graph'
Table 1. Result
name type access currentStatus

"neo4j"

"virtual graph"

"read-only"

"online"

Rows: 1

Supported query shape

The following query shape is generally supported:

  • One or more MATCH clauses including WHERE subclauses.

  • One or more LET or WITH clauses. A WITH before the first MATCH is restricted to constant expressions. A WITH after a MATCH may use DISTINCT, ORDER BY, LIMIT, SKIP and WHERE, and may separate multiple match clauses, as in MATCH …​ WITH …​ MATCH. An aggregating WITH is only supported when it is the last clause before the RETURN.

  • A leading UNWIND clause over a list. UNWIND in other positions is handled by post-processing (see List operations).

  • A single, non-nested CALL subquery just before the RETURN clause (see Subquery expressions and CALL clauses).

  • A RETURN clause, optionally with DISTINCT, including ORDER BY, LIMIT, SKIP and GROUP BY subclauses and some aggregations.

  • UNION and UNION ALL of queries of this shape.

Or, more formally:

(WITH | LET)?
UNWIND?
(MATCH+ (WITH | LET)?)+
CALL?
RETURN
  (ORDER BY)?
  (GROUP BY)?
  SKIP?
  LIMIT?

(UNION (ALL)? <query of this shape>)*

Virtual Graph pushes as much of the query as it can to SQL and executes the rest in Cypher as post-processing. Post-processing is needed, for example:

Post-processing materializes intermediate results, that is, it fetches them from the remote source and holds them in memory before the rest of the query runs in Cypher. This may transfer large amounts of data from the remote source and increase memory usage, so such queries raise a notification with the GQLSTATUS code 03N97. To avoid it, consider rewriting the query so that aggregation, ORDER BY, DISTINCT, SKIP and LIMIT can be pushed down to the remote source.

Supported patterns

Not all patterns are supported. Some examples of supported patterns:

  • (n) - nodes without label.

  • (n {name: 'The Name'}) - nodes with inline property predicate (the same holds for relationships).

  • (n:Movie) - nodes with a single label.

  • (n:Movie|Person) - nodes with label union and other combinations of logical operators, for example (n:Movie&Person) and (n:!Movie).

  • (a:A)-[r0:R]→(b:B)←[r1]-(c:C) - relationship chains of any length and direction, with node labels and types as above.

  • (a:A)-[r:R]-(b:B) - undirected patterns.

  • p = (a:A)-[r:R]→(b:B) - named paths.

  • Several patterns in one MATCH, and several MATCH clauses, including re-matching the same variable.

Quantified path patterns

Quantified path patterns (QPPs) are supported in a restricted form:

  • Only fixed-bound intervals of the form {1,N} are supported. For example, (a)-[r:R]→{1,3}(b) and a)-[r:R]→(b{1,3}.

  • The relationships inside a QPP must be directed.

  • Label unions and relationship type unions are not supported inside a QPP.

  • A QPP must be the only path pattern in its MATCH clause, and QPPs are only supported in a query with a single MATCH clause, or inside a CALL subquery.

  • WHERE predicates inside the quantified part are supported, for example ((a)-[r:R]→(b) WHERE r.amount > 100){1,3}.

Supported expressions

Support for expressions is dependent on the subclause the expression is part of:

  • See Expressions in WHERE clauses for expressions in WHERE clauses.

  • Expressions in ORDER BY clauses work similarly to expressions in WHERE clauses, unless the ORDER BY is applied during post-processing (see Aggregations).

  • Expressions in RETURN clauses are less restricted because expressions that have no SQL equivalent are computed in Cypher (post-processing). Most non-aggregating expressions are supported in the scope of RETURN.

The following functions are supported:

  • Comparison, boolean and string predicates (=, <>, <, ⇐, >, >=, AND, OR, NOT, XOR, IN, STARTS WITH, ENDS WITH, CONTAINS, =~, IS NULL, IS NOT NULL).

  • Conditional: CASE.

  • Schema: labels(), type(), elementId().

  • Type conversion: toInteger(), toFloat(), toBoolean(), toString().

  • String: toLower(), toUpper(), reverse(), size(), ltrim(), rtrim(), trim(), left(), right(), split(), substring(), replace(), coalesce().

  • Arithmetic: +, -, *, /, % and unary -.

  • Math: abs(), floor(), ceil(), round(), sign(), sqrt(), exp(), log(), log10(), ^.

  • Trigonometry: sin(), cos(), tan(), asin(), acos(), atan(), atan2(), degrees(), radians().

  • Constants: pi(), e().

Literal temporal values and calls to temporal construction functions (for example date() and datetime()) are supported as constants.

Other functions, including user-defined functions such as those from APOC or GDS, are supported in RETURN items and are computed in Cypher during post-processing. They are not supported in MATCH …​ WHERE clauses.

Aggregations

MATCH (movie:Movie)
RETURN movie.release_year, count(movie)

The following aggregations are supported:

  • count() and count(*)

  • sum()

  • min() and max()

  • avg()

  • collect()

DISTINCT is supported inside these aggregations where it has an effect.

If a query contains an aggregation and at least one of its return items cannot be pushed to SQL, the aggregation is handled during post-processing instead. In that case, ORDER BY, SKIP and LIMIT are also applied during post-processing.

Limitations

Queries using unsupported features fail with the GQL error 42NG1, whose description names the unsupported part, for example Unsupported syntax: OPTIONAL MATCH .

Write queries

Write queries are currently not supported. Virtual Graph only reads data, but doesn’t alter them via write operations.

This includes:

  • CREATE

  • MERGE

  • SET

  • INSERT

  • DELETE

  • REMOVE

  • DROP

  • ALTER

  • START

  • STOP

  • GRANT

  • REVOKE

WITH clauses

A WITH clause after a MATCH is pushed to SQL, including DISTINCT, ORDER BY, SKIP, LIMIT and WHERE. An initial WITH before the first MATCH is restricted to constant expressions.

A WITH that is followed by another MATCH must be pushed to SQL, because the following MATCH cannot be post-processed. A WITH that is the last clause before the RETURN is evaluated in Cypher post-processing (see Post-processing in Cypher) if it cannot be pushed to SQL. This includes aggregating WITH clauses, for example MATCH (n) WITH n.x, count(*) AS c RETURN …​, which are supported only in this position and are always handled in post-processing. An aggregating WITH cannot be followed by another MATCH.

A WITH that must be pushed to SQL does not support:

  • Aggregations.

  • Non-deterministic WHERE predicates, such as WHERE rand() > 0.5, that don’t always yield the same result.

  • WHERE combined with SKIP or LIMIT.

  • DISTINCT for expressions that cannot be de-duplicated in SQL.

  • ORDER BY in a DISTINCT WITH for expressions that the WITH does not project.

List operations

A leading UNWIND over a list or a list parameter, for example UNWIND [1, 2, 3] AS x MATCH …​, is pushed to SQL. It may be preceded with a WITH clause defining a constant, but a WITH directly after a leading UNWIND is not supported.

UNWIND after a MATCH, for example MATCH (n) WITH n UNWIND keys(n) AS k RETURN k, is executed in post-processing. This also covers UNWIND range(…​), chained UNWIND clauses and unwinding collected lists.

Post-processing in Cypher

Some queries cannot be fully pushed to SQL and need post-processing in Cypher. The following are rejected:

  • DISTINCT combined with SKIP/LIMIT in a RETURN whose items require post-processing.

  • Subquery expressions and MATCH clauses in the post-processed part of the query, for example a MATCH after a WITH whose items need post-processing.

  • ORDER BY expressions that cannot be pushed to SQL when there is no post-processing, see Expressions in WHERE clauses.

Variable length paths

Variable length paths such as (:A)-[:R*1..5]→(:B) and -[:R*]→ are currently not supported. Use a quantified path pattern with an explicit upper bound instead. Shortest path patterns (SHORTEST, ANY SHORTEST, ALL SHORTEST, SHORTEST k) are also not supported.

Match clauses

OPTIONAL MATCH, USING hints, SEARCH, the REPEATABLE ELEMENTS match mode, and match selectors are not supported.

Nodes carried forward by WITH can be re-matched in a later MATCH, but relationships cannot, for example MATCH ()-[r]→() WITH r MATCH ()-[r]→().

Expressions in WHERE clauses

Expressions in MATCH …​ WHERE clauses such as MATCH (n) WHERE n.p > 1 are currently restricted because they are always evaluated in SQL. A WHERE attached to a WITH is evaluated as part of that WITH, see WITH clauses.

This affects comparisons, type casts, arithmetic, trigonometric, String and aggregation functions. Expressions that cannot be mapped to SQL are rejected.

Subquery expressions and CALL clauses

Subquery expressions (for example EXISTS { MATCH (:X) }) are not supported.

CALL subqueries are supported with restrictions:

MATCH (m:Movie)
CALL (m) {
  MATCH (actor:Person)-[:ACTED_IN]->(m)
  RETURN count(actor) AS actorCount
}
RETURN m.title, actorCount
  • Variables must be imported with a variable scope clause, CALL (var, …​) { …​ } or CALL (*) { …​ }. The older importing WITH form (CALL { WITH var …​ }) is not supported.

  • Imported variables must be used in a pattern inside the subquery.

  • Only a single, non-nested CALL is supported, and it must come after the last MATCH of the query (no MATCH after the CALL).

  • The subquery can return scalars, aggregations, nodes, relationships and paths (including quantified paths).

  • DISTINCT, ORDER BY, SKIP, LIMIT and aggregating WITH clauses are not supported inside a CALL subquery, and IN TRANSACTIONS is not supported.

  • OPTIONAL CALL is supported, but cannot return nodes, relationships or paths.

Procedure calls (CALL …​ YIELD …​) are supported, as standalone or before a RETURN, and are always executed in Cypher post-processing.

Runtimes

Only the default and pipelined runtimes are supported. Specifying another runtime, for example CYPHER runtime=slotted, raises an error.

Currently not supported.

APOC

Most APOC procedures and functions are not supported. A few are emulated for convenience: apoc.meta.stats(), apoc.meta.schema() and apoc.convert.toJson().

Built-in schema procedures such as db.labels(), db.relationshipTypes(), db.propertyKeys(), db.schema.visualization(), db.schema.nodeTypeProperties() and db.schema.relTypeProperties() are supported.

Checking for entities that do not exist

Checks for non-existent entities, for example n.property IS NULL or NOT (n:Label), are supported as described in Supported expressions. Other handling of null values may still deviate from Cypher in post-processing.