Neo4j Driver API
Neo4j Drivers export a uniform API. This allows driver concepts and naming to be shared across ecosystems, making transition between languages and multi-language support easier and more consistent.
Driver objects
-
Driver
-
Session
-
Transaction
-
DriverConfig
-
uri::String
-
auth::Dictionary
-
user_agent::String
-
encrypted::Boolean
-
trust::String
-
-
SessionConfig
-
default_access_mode::String
-
database::String
-
fetch_size::Integer
-
bookmarks::List<String>
-
imp_user::String
-
-
TransactionConfig
-
metadata::Dictionary
-
timeout::Integer
-
-
AuthToken
-
TransactionManager
-
Connection pool
-
Routing
-
Bolt Protocol
-
PackStream
-
Neo4jExceptions
-
DriverExceptions
URI schemes
No TLS enabled:
-
bolt
: connect to a single Neo4j instance. -
neo4j
: connect to a Neo4j instance and use the routing table information for further connections.
Enable TLS and allow self-signed certificate authority:
-
bolt+ssc
-
neo4j+ssc
Enable TLS and only allow system enabled certificate authority and verify hostname:
-
bolt+s
-
neo4j+s
Client-side routing
Neo4j supports clustered setups and uses The Raft Consensus Algorithm.
Each Neo4j primary server in a cluster supports routing
and reading
.
Only one cluster primary can be selected as leader, who is in charge of write
operations.
This selection can rotate over time.
The driver should support a routing table.
Secondary servers are not involved in the Raft Consensus Algorithm, but secondaries do return a routing table that only contain the secondary itself.
See Operations Manual → Clustering for more information.
Fetching routing tables
The procedure call to fetch the routing table has changed considerably throughout the various versions of Neo4j.
Neo4j | Bolt | Bolt message |
---|---|---|
4.3 |
4.3 |
|
4.4 |
4.4 |
|
Neo4j | Bolt | Bolt message |
---|---|---|
4.3 |
4.3 |
|
4.4 |
4.4 |
|
C: 60 60 B0 17
C: 00 00 04 04 00 00 00 00 00 00 00 00 00 00 00 00
S: 00 00 04 04
C: HELLO {"scheme": "basic", "principal": "user", "credentials": "password", "user_agent": "Example/4.4.0", "routing": {"address": "localhost:9001", "policy": "example_policy", "region": "example_region"}}
S: SUCCESS {"server": "Neo4j/4.4.0", "connection_id": "bolt-123456789"}
C: ROUTE {"address": "localhost:9001", "policy": "example_policy", "region": "example_region"} ["neo4j-bookmark-transaction:1", "neo4j-bookmark-transaction:2"], {}
S: SUCCESS {"rt": {"ttl": 300, "db": "foo", "servers": [{"addresses": ["127.0.0.1:9001"], "role": "WRITE"}, {"addresses": ["127.0.0.1:9002"], "role": "READ"}, {"addresses": ["127.0.0.1:9001", "127.0.0.1:9002"], "role": "ROUTE"}]}}
C: GOODBYE
Procedure call <4.2
Neo4j | Bolt | Neo4j Procedure call |
---|---|---|
3.5 |
3 |
|
4.0 |
4.0 |
|
4.1 |
4.1 |
|
4.2 |
4.2 |
Neo4j | Bolt | Bolt message |
---|---|---|
3.5 |
3 |
|
4.0 |
4.0 |
|
4.1 |
4.1 |
|
4.2 |
4.2 |
|
C: 60 60 B0 17
C: 00 00 01 04 00 00 00 00 00 00 00 00 00 00 00 00
S: 00 00 01 04
C: HELLO {"scheme": "basic", "principal": "user", "credentials": "password", "user_agent": "Example/4.1.0", "routing": {"address": "localhost:9001", "policy": "example_policy", "region": "example_region"}}
S: SUCCESS {"server": "Neo4j/4.1.0", "connection_id": "bolt-123456789"}
C: RUN "CALL dbms.routing.getRoutingTable($context)" {"context": {"address": "localhost:9001", "policy": "example_policy", "region": "example_region"}} {"mode": "r", "db": "system"}
C: PULL {"n": -1}
S: SUCCESS {"fields": ["ttl", "servers"]}
S: RECORD [300, [{"addresses": ["127.0.0.1:9001"], "role": "WRITE"}, {"addresses": ["127.0.0.1:9002"], "role": "READ"}, {"addresses": ["127.0.0.1:9001", "127.0.0.1:9002"], "role": "ROUTE"}]]
S: SUCCESS {"bookmark": "example-bookmark:1", "type": "r", "t_last": 5, "db": "system"}
C: GOODBYE
Clusters and multiple databases
System database
-
The name of the system database is fixed and named
system
. -
The system database cannot be changed for a single instance or a cluster.
-
The system database exists on each instance.
Cluster member
A cluster contains primary members and secondary members.
-
Only one primary at any time can be the leader (accept
writes
). -
Each database in a cluster has its own raft group and each database has its own routing table. In other words, the leader/primary/secondary for each database in a cluster can be different.
-
Any primary member in a cluster can provide a routing table for any database inside this cluster. Given a seed URL pointing to a primary member, this can be used to find any databases in a cluster by fetching the routing table from a primary member.
Moreover, in Neo4j 4.x:
These do not apply in Neo4j 5.x. |
Driver routing table
The Driver should prevent the routing table from growing infinitely. The routing table for a specific database should be removed from the routing table if there is a failed to attempt to obtain routing information. The routing table for a specific database should be removed from the routing table if it is invalid. An invalid routing table could either be a:
-
routing table that has timed out where the
TTL
(Time To Live) key for that routing table have ended. -
routing table that is pointing to a database that no longer exists.
This is the workflow the driver should follow when fetching a routing table for database named foo
.
-
Find the routing table for database
foo
. -
If the database does not exist in the routing table, then create an empty routing table with seed URL as initial router.
-
If the routing table is stale, then refresh the routing table with a query to a cluster member that.
-
If any error happens, remove the key
foo
from routing table map.
The only errors possible are:
-
SECURITY_ERROR
-
ROUTING_ERROR
-
SERVICE_UNAVAILABLE_ERROR
, happens when the driver failed to get routing table for all existing routers.