Migrating from Neo4j to SurrealDB
This page details some Neo4j data types and patterns in the Cypher query language along with their SurrealQL equivalents or near equivalents, followed by links to the Surreal Sync tool which allows data from Neo4j to be automatically imported to SurrealDB.
Concept mapping
| Neo4j | SurrealDB |
|---|
database | database |
node label | table |
node | record |
node property | field |
index | index |
id | record id |
transactions | transactions |
relationships | record links, embedding and graph relations |
Data types
The following chart shows Neo4j data types along with the equivalent or near-equivalent SurrealQL data type for each.
| Neo4j Data Type | SurrealDB Mapping | Notes |
|---|
| Boolean | bool | |
| Integer | int | |
| Float | float (f64) | |
| String | string | |
| List | array | |
| Map | object | |
| Null | null | |
| Date | datetime | Convert to UTC datetime (assuming local timezone) |
| DateTime | datetime | Convert to UTC datetime |
| LocalDateTime | datetime | Convert to UTC datetime (assuming UTC) |
| Duration | duration | |
| Bytes | bytes | |
| Time | object | Convert to object with type: "$Neo4jTime", hour, minute, second, nanosecond, offset_seconds fields |
| LocalTime | object | Convert to object with type: "$Neo4jLocalTime", hour, minute, second, nanosecond fields |
| Point2D | object | Convert to GeoJSON-like object with type: "Point", srid (4326), coordinates: [longitude, latitude] |
| Point3D | object | Convert to GeoJSON-like object with type: "Point", srid (4979), coordinates: [longitude, latitude, elevation] |
| DateTimeZoneId | datetime | Convert to UTC datetime using embedded timezone ID |
Syntax mapping
The following shows some CRUD examples using SurrealQL syntax.
Create
As Neo4j is schemaless, only the SurrealQL schemaless approach is shown below. For a schemafull option see the DEFINE TABLE page.
For more SurrealQL examples, see the CREATE, INSERT and RELATE pages.
Simple create/insert operations:
CREATE (John:Person {name:‘John’}), (Jane:Person {name: ‘Jane’})
INSERT INTO person [ {id: “John”, name: “John”}, {id: “Jane”, name: “Jane”} ]
Graph relations via the RELATE statement:
MATCH (p:Person {name:‘Jane’}), (pr:Product {name:‘iPhone’}) CREATE (p)-[:ORDER]->(pr)
RELATE person:Jane->order->product:iPhone
Defining an index:
CREATE INDEX personNameIndex FOR (p:Person) ON (p.name)
DEFINE INDEX idx_name ON TABLE person COLUMNS name
Read
For more SurrealQL examples, see the SELECT, LIVE SELECT and RETURN pages.
Returning all the fields of a table:
MATCH (p:Person) RETURN p
SELECT * FROM person
Returning a single field of a table:
MATCH (p:Person) RETURN p.name
SELECT name FROM person
Using the WHERE clause to return certain records:
MATCH (p:Person) WHERE p.name = “Jane” RETURN p.name
SELECT name FROM person WHERE name = “Jane”
Using EXPLAIN to detail the query plan used:
EXPLAIN MATCH (p:Person) WHERE p.name = "Jane" RETURN p.name
SELECT name FROM person WHERE name = "Jane" EXPLAIN
Grouping and counting the number of records returned:
MATCH (p:Person) RETURN count(*) as person_count
SELECT count() AS person_count FROM person GROUP ALL
See all distinct values for a field among the records of a table:
MATCH (p:Person) RETURN distinct p.name
SELECT array::distinct(name) FROM person GROUP ALL
Returning up to a certain number of records:
MATCH (p:Person) RETURN p LIMIT 10
SELECT * FROM person LIMIT 10
See which person records have ordered a product via the order graph edge:
MATCH (p:Person)-[:ORDER]->(pr:Product) RETURN p.name, pr.name
SELECT name, ->order->product.name FROM person
Update
For more SurrealQL examples, see the UPDATE page.
Conditionally updating records that have a certain value for a field:
MATCH (p:Person) WHERE p.name = "Jane" SET p.last_name = 'Doe' RETURN p
UPDATE person SET last_name = "Doe" WHERE name = "Jane"
Unsetting (removing) the value of a field for certain records:
MATCH (p:Person) WHERE p.name = "Jane" REMOVE p.last_name RETURN p
UPDATE person UNSET last_name WHERE name = "Jane"
Delete
For more SurrealQL examples, see the DELETE and REMOVE pages.
Conditionally deleting records based on the value of a field:
MATCH (p:Person) WHERE p.name = "Jane" DELETE p
DELETE person WHERE name = "Jane"
Deleting all records for a table (SurrealQL: table still exists):
MATCH (p:Person) DELETE p
DELETE person
Deleting all records and table definition for a table:
MATCH (p:Person) DELETE p
REMOVE TABLE person
Importing from Neo4j using Surreal Sync
Surreal Sync can be used to export Neo4j nodes and relationships to SurrealDB.
It supports inconsistent full syncs and consistent incremental syncs, and together provides ability to reproduce consistent snapshots from the source Neo4j graph onto the target SurrealDB tables.
For more on how to import data from Neo4j to SurrealDB, please see the following pages in the Surreal Sync repo.