Introduction

ArcadeDB provides native support for the Cypher query language through a new, high-performance implementation built from the ground up. This native OpenCypher module uses an ANTLR4-based parser with the official Cypher 2.5 grammar, providing excellent compatibility and performance.

Deprecation Notice: Legacy Cypher Implementation

ArcadeDB includes two Cypher implementations:

  • opencypher (NEW) - Native implementation with direct execution. This is the recommended query language for new projects.

  • cypher (DEPRECATED) - Legacy implementation based on Cypher for Gremlin. This will be removed in a future release.

The legacy cypher query language translates Cypher queries to Gremlin, which results in slower performance (up to 20x slower for complex queries) and limited feature support. We strongly recommend migrating to opencypher for all new and existing projects.

To migrate: Simply change your query language from cypher to opencypher. The syntax is identical for supported features.

Key Features

The native OpenCypher implementation provides:

  • High Performance: Direct execution without Gremlin translation, comparable to native SQL

  • Full Read/Write Support: MATCH, CREATE, MERGE, SET, DELETE with automatic transaction handling

  • Advanced Pattern Matching: Variable-length paths with path modes (WALK, TRAIL, ACYCLIC), OPTIONAL MATCH, multiple MATCH clauses

  • Query Composition: UNION/UNION ALL for combining results, WITH for query chaining

  • Procedures and Profiling: CALL for invoking built-in procedures and custom functions, PROFILE for performance analysis

  • Rich Function Library: 23+ native Cypher functions plus bridge to 100+ ArcadeDB SQL functions

  • Cost-Based Optimizer: Intelligent query planning with index selection and join ordering

  • 100% Test Coverage: Comprehensive test suite with 295+ passing tests

Using OpenCypher

To execute OpenCypher queries, use opencypher as the query language identifier.

From Java API:

ResultSet result = database.query("opencypher",
    "MATCH (p:Person) WHERE p.age >= $minAge RETURN p.name, p.age ORDER BY p.age",
    "minAge", 25);

Through Neo4j BOLT Protocol (v26.2.1+):

Connect using any Neo4j driver via the BOLT protocol:

Driver driver = GraphDatabase.driver("bolt://localhost:7687", AuthTokens.basic("root", "password"));
Session session = driver.session(SessionConfig.forDatabase("mydatabase"));
Result result = session.run("MATCH (p:Person) WHERE p.age >= 25 RETURN p.name, p.age ORDER BY p.age");

Through PostgreSQL Driver:

Prefix your query with {opencypher}:

"{opencypher} MATCH (p:Person) WHERE p.age >= 25 RETURN p.name, p.age ORDER BY p.age"

Through HTTP/JSON API (GET - idempotent queries):

curl "http://localhost:2480/query/graph/opencypher/MATCH%20(p:Person)%20RETURN%20p"

Through HTTP/JSON API (POST - updates):

curl -X POST "http://localhost:2480/command/graph" \
  -d "{'language': 'opencypher', 'command': 'CREATE (p:Person {name: \"Alice\", age: 30})'}"

Using Record IDs (RIDs)

You can use ArcadeDB’s RecordIDs (RID) in Cypher queries to start from a specific vertex. RIDs in Cypher are always strings, so they must be contained between single or double quotes.

MATCH (m:Movie)<-[a:ACTED_IN]-(p:Person) WHERE id(m) = '#1:0' RETURN *

Parameters

OpenCypher supports parameterized queries using the $paramName syntax:

MATCH (p:Person) WHERE p.age >= $minAge AND p.city = $city RETURN p

Parameters are passed as key-value pairs after the query string:

ResultSet result = database.query("opencypher",
    "MATCH (p:Person) WHERE p.age >= $minAge RETURN p",
    "minAge", 25);

Automatic Transaction Handling

All write operations (CREATE, SET, DELETE, MERGE) automatically handle transactions:

  • If no transaction is active, the operation creates, executes, and commits its own transaction

  • If a transaction is already active, the operation reuses it without committing

  • Proper rollback on errors for self-managed transactions

// Automatic transaction - commits automatically
database.command("opencypher", "CREATE (n:Person {name: 'Alice'})");

// Manual transaction - you control commit/rollback
database.transaction(() -> {
    database.command("opencypher", "CREATE (a:Person {name: 'Alice'})");
    database.command("opencypher", "CREATE (b:Person {name: 'Bob'})");
    database.command("opencypher", "MATCH (a:Person {name: 'Alice'}), (b:Person {name: 'Bob'}) CREATE (a)-[:KNOWS]->(b)");
    // Commits when lambda completes successfully
});

Performance Considerations

The native OpenCypher implementation includes a cost-based query optimizer that:

  • Automatically selects optimal indexes for node lookups

  • Uses range index scans for inequality predicates (>, <, >=, )

  • Optimizes join order based on cardinality estimation

  • Detects bounded patterns for efficient relationship traversal

For best performance:

  • Create indexes on frequently queried properties

  • Use labeled nodes in MATCH patterns for faster type filtering

  • Prefer specific property constraints over full scans

  • Use parameters for queries executed multiple times (enables query plan caching)

Comparison with Legacy Cypher

Feature opencypher (NEW) cypher (DEPRECATED)

Execution

Native, direct

Gremlin translation

Performance

Fast (comparable to SQL)

Slow (up to 20x slower)

Write Operations

Full support

Limited support

OPTIONAL MATCH

Supported

Partial support

Variable-length Paths

Supported

Limited

UNION / UNION ALL

Supported

Not supported

CALL Procedures

Supported

Not supported

PROFILE

Supported

Not supported

Aggregations

Full support

Limited

Functions

100+ functions

Limited

Transaction Handling

Automatic

Manual

Active Development

Yes

No (abandoned upstream)