Migrating from Neo4j
Overview
For developers migrating from Neo4j or evaluating HugeGraph. HugeGraph supports openCypher declarative query syntax, but differences exist in the graph model, schema rules, parameter bindings, and indexing. For language usage and compatibility references, see HugeGraph Cypher and Cypher Compatibility.
What carries over directly
| Neo4j concept | HugeGraph equivalent |
|---|---|
| Property graph model (nodes / relationships / properties) | Same — vertex labels / edge labels / properties |
Core Cypher: MATCH/WHERE/RETURN/CREATE/SET/DELETE | Works as-is (REST /cypher endpoint or Java client CypherManager), subject to the schema and index rules below |
Simple aggregations (count/sum/min/max/avg) | Works as-is |
| Traversal-heavy queries | Gremlin traversals or the traverser REST APIs (k-out, shortest path, personalrank, …) |
Habits you need to change
| In Neo4j | In HugeGraph |
|---|---|
CREATE INDEX / CREATE CONSTRAINT | Create property indexes through the IndexLabel REST API; uniqueness constraints map to UNIQUE IndexLabels; node keys map to non-nullable keys plus a composite UNIQUE index; property existence constraints map to non-nullable keys on VertexLabels or EdgeLabels. Note that primary_keys defines vertex identity, not a uniqueness constraint — a duplicate CREATE overwrites the existing vertex instead of failing |
| Implicit schema (add properties freely) | Strong schema: define VertexLabel / EdgeLabel / PropertyKey before writing data |
Property predicates in WHERE need no index | The starting vertex lookup in WHERE needs a covering index unless it is an equality on every primary key of the label. Use RANGE for > / < comparisons. Without a covering index the request returns HTTP 200 with status.code 400 and a “not indexed” error |
Parameterized queries $param | Parameterized requests are supported via JSON body (up to 16 top-level parameters; group additional values into a nested Map); missing parameters result in execution errors |
CALL dbms.* / CALL algo.* procedures | Equivalent capabilities are in the traverser, task, and other REST APIs |
| Driver: Neo4j Bolt driver | hugegraph-client (CypherManager) or any HTTP client |
| Transaction boundaries inside a Cypher statement | One statement per request; graph-to-graph migration uses Apache SeaTunnel 3.0.0 (preferred, see below), file-based bulk loads use the HugeGraph Loader |
On PRIMARY_KEY labels, a UNIQUE index cannot include all primary-key fields
(the server rejects it). To keep duplicate-rejection behavior, use a
CUSTOMIZE_STRING label keyed on the Neo4j node id and add a UNIQUE index on the
business key.
Suggested migration path
Inventory your queries: Review your application’s Cypher queries against the Cypher Compatibility Notes and Known Limitations to classify them into “works as-is”, “rewrite as Gremlin”, or “switch to a REST API”.
Create the schema first: define VertexLabel / EdgeLabel / PropertyKey and indexes through the schema API — HugeGraph requires the schema to exist before data is written.
Import data: the preferred path is Apache SeaTunnel 3.0.0 (released 2026-09-29) running Neo4j Source → HugeGraph Sink directly — no intermediate file export. REST remains fine for small datasets; the HugeGraph Loader stays an alternative for file-based imports. HugeGraph-side setup (environment,
mappings, vertex/edge import examples) is covered in the Import Graph Data with SeaTunnel Sink guide.The SeaTunnel 3.0.0 connector docs document what to rely on:
- Neo4j Source reads Cypher
query results with explicit field schemas; 3.0.0 adds multi-table reads via
tables_configs. - HugeGraph Sink is
refactored in 3.0.0 with multi-mapping support — use the recommended
mappingsconfiguration for vertices/edges and follow its schema-creation behavior. By default, the Sink fails fast on errors (batch_failure_fallback=falseandmax_insert_errors=0). Record skipping is opt-in viabatch_failure_fallback=true; if enabled, capture and reconcile skipped records and compare row counts before cutover. - HugeGraph Source is new in 3.0.0 (schema auto-discovery, multi-label/parallel reads), enabling HugeGraph export and migration workflows.
Map Neo4j properties to HugeGraph PropertyKeys and pick the vertex ID strategy before importing. The Sink requires
idFieldsfor every vertex strategy other thanAUTOMATIC, and edge mappings need separatesourceConfig.idFieldsandtargetConfig.idFields, so the Neo4j query must return the field that carries the ID:idStrategy = "PRIMARY_KEY": put a Neo4j business key inidFieldsand express edge endpoints through those same key fields.idStrategy = "CUSTOMIZE_STRING": this alone does not keep the Neo4j node id. Make the Neo4j query return the id you want to keep as its own column (aliased, for exampleAS node_id), declare that field in the Sourceschema.fields(it must match the fields the query returns), set the vertexidFieldsto it, and map the matching edge endpoint fields insourceConfig.idFieldsandtargetConfig.idFields.
Labels you pre-created in step 2 must use that same strategy — automatic creation does not convert an existing
PRIMARY_KEYlabel intoCUSTOMIZE_STRING. The Sinkmappingsconfiguration can create the missing PropertyKey, VertexLabel and EdgeLabel definitions, so those three parts of step 2 are optional when you use it; it does not create IndexLabels, so create any index your queries rely on (see the habits table above) separately. When SeaTunnel auto-creates EdgeLabels, omittingfrequencydefaults toSINGLE, which collapses parallel Neo4j relationships between the same endpoints into a single edge. To preserve parallel relationships, explicitly specifyfrequency = "MULTIPLE"and provide stable relationship discriminator fields assortKeysin the edge mapping (HugeGraph uses sort keys to distinguish parallel edges). Load vertices before edges. We recommend thoroughly testing the import pipeline with a representative data sample before cutover.- Neo4j Source reads Cypher
query results with explicit field schemas; 3.0.0 adds multi-table reads via
Switch incrementally: keep queries Cypher supports, and rewrite unsupported constructs as Gremlin — the equivalents table shows the mapping.
Limitations at a glance
- Statements and parameters: Multi-statement scripts and
CALLprocedures are not supported; parameter binding supports up to 16 top-level parameters (pass a nested Map for additional properties). - Unsupported syntax: Advanced openCypher clauses not covered in the compatibility matrix will fail during query validation.
- Fallback path: Unsupported query constructs can typically be rewritten as Gremlin traversals — see the equivalents table; schema DDL and procedures map to REST APIs instead.