Data types and mapping to Cypher types

The tables in this section show the mapping between Cypher data types and Java types.

Regardless of their type, all values in query results are embedded within Value objects. To extract and cast them to the corresponding Java types, use .as<type>() (eg. .asString(), asInt(), etc). For example, if the name property coming from the database is a string, record.get("name").asString() will yield the property value as a String object.

On the other hand, you don’t need to use the driver types when submitting query parameters. The driver will automatically serialize objects of native Java types passed as parameters.

For a complete list of the value types the driver serializes data into, see the API documentation.

Core types

Cypher type Driver type

NULL

NullValue

LIST

ListValue

MAP

MapValue

BOOLEAN

BooleanValue

INTEGER

IntegerValue

FLOAT

FloatValue

STRING

StringValue

ByteArray

BytesValue

Temporal types

The driver provides a set of temporal data types compliant with ISO-8601 and Cypher. Sub-second values are measured to nanosecond precision.

The driver’s types rely on Java’s time types. All temporal types, except DurationValue, are in fact java.time objects under the hood. This means that:

  • if you want to query the database with a temporal type, instantiate a java.time object and use it as query parameter (i.e. you don’t need to care about driver’s types).

  • if you retrieve a temporal object from the database (including through one of Cypher temporal functions), you will get back the corresponding driver type as displayed in the table below. The driver implements methods to convert driver time types into Java ones (ex. .asZonedDateTime(), .asOffsetTime(), etc).

Cypher type Driver type

DATE

DateValue

ZONED TIME

TimeValue

LOCAL TIME

LocalTimeValue

ZONED DATETIME

DateTimeValue

LOCAL DATETIME

LocalDateTimeValue

DURATION

DurationValue

How to use temporal types in queries
package demo;

import java.util.Map;
import java.time.ZonedDateTime;
import java.time.ZoneId;

import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;
import org.neo4j.driver.QueryConfig;

public class App {

    public static void main(String... args) {
        final String dbUri = "<URI for Neo4j database>";
        final String dbUser = "<Username>";
        final String dbPassword = "<Password>";

        try (var driver = GraphDatabase.driver(dbUri, AuthTokens.basic(dbUser, dbPassword))) {
            driver.verifyConnectivity();

            // Define a date, with timezone, and use it to set a relationship property
            var friendsSince = ZonedDateTime.of(2016, 12, 16, 13, 59, 59, 9999999, ZoneId.of("Europe/Stockholm"));
            var result = driver.executableQuery("""
                MERGE (a:Person {name: $name})
                MERGE (b:Person {name: $friend})
                MERGE (a)-[friendship:KNOWS {since: $friendsSince}]->(b)
                RETURN friendship.since AS date
                """)
                .withParameters(Map.of("name", "Alice", "friend", "Bob", "friendsSince", friendsSince))
                .withConfig(QueryConfig.builder().withDatabase("neo4j").build())
                .execute();

            var date = result.records().get(0).get("date");
            System.out.println(date.getClass().getName());  // org.neo4j.driver.internal.value.DateTimeValue
            System.out.println(date);  // 2016-12-16T13:59:59.009999999+01:00[Europe/Stockholm]

            var nativeDate = date.asZonedDateTime();
            System.out.println(nativeDate.getClass().getName());  // java.time.ZonedDateTime
        }
    }
}

DurationValue

Represents the difference between two points in time (expressed in months, days, seconds, nanoseconds).

// import org.neo4j.driver.Values;

var duration = Values.isoDuration(1, 2, 3, 4);  // months, days, seconds, nanoseconds
System.out.println(duration);  // P1M2DT3.000000004S

For full documentation, see API documentation → DurationValue.

Spatial types

Cypher supports spatial values (points), and Neo4j can store these point values as properties on nodes and relationships.

The attribute SRID (short for Spatial Reference Identifier) is a number identifying the coordinate system the spatial type is to be interpreted in. You can think of it as a unique identifier for each spatial type.

Cypher type Driver type SRID

POINT (2D Cartesian)

PointValue

7203

POINT (2D WGS-84)

PointValue

4326

POINT (3D Cartesian)

PointValue

9157

POINT (3D WGS-84)

PointValue

4979

You create a point value through Values.point(srid, x, y[, z]) (the third coordinate is optional). Points returned from database queries are of type PointValue, and can be converted to Point objects through the method .asPoint().

Receive a Point value from the database
package demo;

import java.util.Map;

import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;
import org.neo4j.driver.QueryConfig;
import org.neo4j.driver.Values;

public class App {

    public static void main(String... args) {
        final String dbUri = "<URI for Neo4j database>";
        final String dbUser = "<Username>";
        final String dbPassword = "<Password>";

        try (var driver = GraphDatabase.driver(dbUri, AuthTokens.basic(dbUser, dbPassword))) {
            driver.verifyConnectivity();

            var result = driver.executableQuery("RETURN point({x: 2.3, y: 4.5, z: 2}) AS point")
                .withConfig(QueryConfig.builder().withDatabase("neo4j").build())
                .execute();
            var point = result.records().get(0).get("point");
            System.out.println(point);  // Point{srid=9157, x=2.3, y=4.5, z=2.0}
            System.out.println(point.asPoint().x());  // 2.3
        }
    }
}
Create a Point value and use it as property value
package demo;

import java.util.Map;

import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;
import org.neo4j.driver.QueryConfig;
import org.neo4j.driver.Values;

public class App {

    public static void main(String... args) {
        final String dbUri = "<URI for Neo4j database>";
        final String dbUser = "<Username>";
        final String dbPassword = "<Password>";

        try (var driver = GraphDatabase.driver(dbUri, AuthTokens.basic(dbUser, dbPassword))) {
            driver.verifyConnectivity();

            var location = Values.point(4326, 67.28775180193841, 17.734163823312397);  // 4326 = 2D geodetic point
            var result = driver.executableQuery("CREATE (p:PlaceOfInterest {location: $location}) RETURN p")
                .withParameters(Map.of("location", location))
                .withConfig(QueryConfig.builder().withDatabase("neo4j").build())
                .execute();
            var place = result.records().get(0).get("p").get("location");
            System.out.println(place);  // Point{srid=4326, x=67.28775180193841, y=17.734163823312397}
            System.out.println(place.asPoint().y());  // 17.734163823312397
        }
    }
}

Graph types

Graph types are only passed as results and may not be used as parameters.

Cypher Type Driver type

NODE

NodeValue

RELATIONSHIP

RelationshipValue

PATH

PathValue

NodeValue

Represents a node in a graph.

Table 1. Essential methods on node objects
Method Return

.labels()

Node labels, as a list.

.asMap()

Node properties, as a map.

.get("<propertyName>")

Value for the given property.

.elementId()

String identifier for the relationship. This should be used with care, as no guarantees are given about the mapping between id values and elements outside the scope of a single transaction. In other words, using an elementId to MATCH an element across different transactions is risky.

Retrieve a node and display its details
package demo;

import java.util.Map;

import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;
import org.neo4j.driver.QueryConfig;

public class App {

    public static void main(String... args) {
        final String dbUri = "<URI for Neo4j database>";
        final String dbUser = "<Username>";
        final String dbPassword = "<Password>";

        try (var driver = GraphDatabase.driver(dbUri, AuthTokens.basic(dbUser, dbPassword))) {
            driver.verifyConnectivity();

            // Get a node from the database
            var result = driver.executableQuery("MERGE (p:Person:Actor {name: $name, age: 59}) RETURN p")
                .withParameters(Map.of("name", "Alice"))
                .withConfig(QueryConfig.builder().withDatabase("neo4j").build())
                .execute();

            // Extract node from result
            var nodeVal = result.records().get(0).get("p");
            var node = nodeVal.asNode();  // .asNode() -> type org.neo4j.driver.types.Node

            System.out.printf("Labels: %s %n", node.labels());
            System.out.printf("Properties: %s %n", node.asMap());
            System.out.printf("Name property: %s %n", node.get("name"));
            System.out.printf("Element ID: %s %n", node.elementId());
            /*
            Labels: [Person, Actor]
            Properties: {name=Alice, age=59}
            Name property: "Alice"
            Element ID: 4:549a0567-2015-4bb6-a40c-8536bf7227b0:5
            */
        }
    }
}

For full documentation, see API documentation → NodeValue.

RelationshipValue

Represents a relationship in a graph.

Table 2. Essential methods on relationsip objects
Method Return

.type()

Relationship type.

.asMap()

Relationship properties, as a map.

.get("<propertyName>")

Value for the given property.

.startNodeElementId()

elementId of starting node.

.endNodeElementId()

elementId of ending node.

.elementId()

String identifier for the relationship. This should be used with care, as no guarantees are given about the mapping between id values and elements outside the scope of a single transaction. In other words, using an elementId to MATCH an element across different transactions is risky.

Retrieve a relationship and display its details
package demo;

import java.util.Map;

import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;
import org.neo4j.driver.QueryConfig;

public class App {

    public static void main(String... args) {
        final String dbUri = "<URI for Neo4j database>";
        final String dbUser = "<Username>";
        final String dbPassword = "<Password>";

        try (var driver = GraphDatabase.driver(dbUri, AuthTokens.basic(dbUser, dbPassword))) {
            driver.verifyConnectivity();

            // Get a relationship from the database
            var result = driver.executableQuery("""
                MERGE (p:Person {name: $name})
                MERGE (p)-[r:KNOWS {status: $status, since: date()}]->(friend:Person {name: $friendName})
                RETURN r AS friendship
                """)
                .withParameters(Map.of("name", "Alice", "status", "BFF", "friendName", "Bob"))
                .withConfig(QueryConfig.builder().withDatabase("neo4j").build())
                .execute();

            // Extract relationship from result
            var relationshipVal = result.records().get(0).get("friendship");
            var relationship = relationshipVal.asRelationship();  // .asRelationship() -> type org.neo4j.driver.types.Relationship

            System.out.printf("Type: %s %n", relationship.type());
            System.out.printf("Properties: %s %n", relationship.asMap());
            System.out.printf("Status property: %s %n", relationship.get("status"));
            System.out.printf("Start node: %s %n", relationship.startNodeElementId());
            System.out.printf("End node: %s %n", relationship.endNodeElementId());
            System.out.printf("Element ID: %s %n", relationship.elementId());
            /*
            Type: KNOWS
            Properties: {since=2024-01-12, status=BFF}
            Status property: "BFF"
            Start node: 4:549a0567-2015-4bb6-a40c-8536bf7227b0:0
            End node: 4:549a0567-2015-4bb6-a40c-8536bf7227b0:6
            Element ID: 5:549a0567-2015-4bb6-a40c-8536bf7227b0:1
            */
        }
    }
}

For full documentation, see API documentation → RelationshipValue.

PathValue

Represents a path in a graph.

The driver breaks paths into (iterable) segments, consisting of a start node, one relationship, and an end node. Segments entities may be retrieved, in order, via the methods .start(), .relationship(), and .end().

Retrieve a path and walk it, listing nodes and relationship
package demo;

import java.util.Map;

import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;
import org.neo4j.driver.types.Path;
import org.neo4j.driver.QueryConfig;

public class App {

    public static void main(String... args) {
        final String dbUri = "<URI for Neo4j database>";
        final String dbUser = "<Username>";
        final String dbPassword = "<Password>";

        try (var driver = GraphDatabase.driver(dbUri, AuthTokens.basic(dbUser, dbPassword))) {
            driver.verifyConnectivity();

            // Create some :Person nodes linked by :KNOWS relationships
            addFriend(driver, "Alice", "BFF", "Bob");
            addFriend(driver, "Bob", "Fiends", "Sofia");
            addFriend(driver, "Sofia", "Acquaintances", "Sofia");

            // Follow :KNOWS relationships outgoing from Alice three times, return as path
            var result = driver.executableQuery("""
                MATCH path=(:Person {name: $name})-[:KNOWS*3]->(:Person)
                RETURN path AS friendshipChain
                """)
                .withParameters(Map.of("name", "Alice"))
                .withConfig(QueryConfig.builder().withDatabase("neo4j").build())
                .execute();

            // Extract path from result
            var pathVal = result.records().get(0).get("friendshipChain");
            var path = pathVal.asPath();  // .asPath() -> type org.neo4j.driver.types.Path

            System.out.println("-- Path breakdown --");
            for (Path.Segment segment : path) {
                System.out.printf(
                    "%s is friends with %s (%s).%n",
                    segment.start().get("name").asString(),
                    segment.end().get("name").asString(),
                    segment.relationship().get("status").asString());
            }
            /*
            -- Path breakdown --
            Alice is friends with Bob (BFF).
            Bob is friends with Sofia (Fiends).
            Sofia is friends with Sofia (Acquaintances).
            */
        }
    }

    public static void addFriend(Driver driver, String name, String status, String friendName) {
        driver.executableQuery("""
            MERGE (p:Person {name: $name})
            MERGE (p)-[r:KNOWS {status: $status, since: date()}]->(friend:Person {name: $friendName})
            """)
            .withParameters(Map.of("name", name, "status", status, "friendName", friendName))
            .withConfig(QueryConfig.builder().withDatabase("neo4j").build())
            .execute();
    }
}

For full documentation, see API documentation → PathValue.

Exceptions

The driver can raise a number of different exceptions, see API documentation → Exceptions. For a list of errors the server can return, see Status codes.

Some server errors are marked as safe to retry without need to alter the original request. Examples of such errors are deadlocks, memory issues, or connectivity issues. Driver’s exceptions implementing RetryableException are such that a further attempt at the operation that caused it might be successful. This is particular useful when running queries in explicit transactions, to know if a failed query is worth re-running.

Glossary

LTS

A Long Term Support release is one guaranteed to be supported for a number of years. Neo4j 4.4 is LTS, and Neo4j 5 will also have an LTS version.

Aura

Aura is Neo4j’s fully managed cloud service. It comes with both free and paid plans.

Cypher

Cypher is Neo4j’s graph query language that lets you retrieve data from the database. It is like SQL, but for graphs.

APOC

Awesome Procedures On Cypher (APOC) is a library of (many) functions that can not be easily expressed in Cypher itself.

Bolt

Bolt is the protocol used for interaction between Neo4j instances and drivers. It listens on port 7687 by default.

ACID

Atomicity, Consistency, Isolation, Durability (ACID) are properties guaranteeing that database transactions are processed reliably. An ACID-compliant DBMS ensures that the data in the database remains accurate and consistent despite failures.

eventual consistency

A database is eventually consistent if it provides the guarantee that all cluster members will, at some point in time, store the latest version of the data.

causal consistency

A database is causally consistent if read and write queries are seen by every member of the cluster in the same order. This is stronger than eventual consistency.

NULL

The null marker is not a type but a placeholder for absence of value. For more information, see Cypher → Working with null.

transaction

A transaction is a unit of work that is either committed in its entirety or rolled back on failure. An example is a bank transfer: it involves multiple steps, but they must all succeed or be reverted, to avoid money being subtracted from one account but not added to the other.

backpressure

Backpressure is a force opposing the flow of data. It ensures that the client is not being overwhelmed by data faster than it can handle.

transaction function

A transaction function is a callback executed by an executeRead or executeWrite call. The driver automatically re-executes the callback in case of server failure.

Driver

A Driver object holds the details required to establish connections with a Neo4j database.