Data types and mapping to Cypher types
The tables in this section show the mapping between Cypher data types and .NET types.
Core types
Cypher type | Driver type |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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.
Time zone names adhere to the IANA system, rather than the Windows system.
Inbound conversion is carried out using Extended Windows-Olson zid mapping as defined by Unicode CLDR.
Cypher type | Driver type |
---|---|
|
|
|
|
|
|
|
|
|
|
|
// Define a date, with timezone, and use it to set a relationship property
var friendsSince = new ZonedDateTime(new DateTime(2016, 12, 16, 13, 59, 59, 999), "Europe/Stockholm");
var result = await 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(new { name = "Astrid", friend = "Sara", friendsSince = friendsSince })
.WithConfig(new QueryConfig(database: "neo4j"))
.ExecuteAsync();
Console.WriteLine(result.Result[0].Get<ZonedDateTime>("date"));
// 2016-12-16T13:59:59.999000000[Europe/Stockholm]
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 |
---|---|---|
|
7203 |
|
|
4326 |
|
|
9157 |
|
|
4979 |
Point
value from the databasevar result = await driver.ExecutableQuery("RETURN point({x: 2.3, y: 4.5, z: 2}) AS point")
.WithConfig(new QueryConfig(database: "neo4j"))
.ExecuteAsync();
Console.WriteLine(result.Result[0].Get<Point>("point"));
// Point{srId=9157, x=2.3, y=4.5, z=2}
Point
value and use it as property valuevar location = new Point(4326, 67.28775180193841, 17.734163823312397); // 4326 = 2D geodetic point
var result = await driver.ExecutableQuery("CREATE (p:PlaceOfInterest {location: $location}) RETURN p")
.WithParameters(new { location = location })
.WithConfig(new QueryConfig(database: "neo4j"))
.ExecuteAsync();
Console.WriteLine(result.Result[0].Get<INode>("p").Get<Point>("location"));
// Point{srId=4326, x=67.28775180193841, y=17.734163823312397}
Graph types
Graph types are only passed as results and may not be used as parameters.
Cypher Type | Driver type |
---|---|
|
|
|
|
|
INode
Represents a node in a graph.
Property/Method | Return |
---|---|
|
Node labels, as a list. |
|
Node properties, as a map. |
|
Value for the given property, casted to |
|
String identifier for the node.
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 |
var result = await driver.ExecutableQuery("MERGE (p:Person:Troublemaker {name: $name, age: $age}) RETURN p")
.WithParameters(new { name = "Carla", age = 59 })
.WithConfig(new QueryConfig(database: "neo4j"))
.ExecuteAsync();
var node = result.Result[0].Get<INode>("p");
Console.WriteLine("Labels: {0}", string.Join(", ", node.Labels));
Console.WriteLine("Properties: {0}", string.Join(", ", node.Properties));
Console.WriteLine("Name property: {0}", node.Get<string>("name"));
/*
Labels: Person, Troublemaker
Properties: [name, Carla], [age, 59]
Name property: Carla
*/
For full documentation, see API documentation → INode.
IRelationship
Represents a relationship in a graph.
Property/Method | Return |
---|---|
|
Relationship type. |
|
Relationship properties, as a map. |
|
Value for the given property, casted to |
|
|
|
|
|
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 |
var result = await driver.ExecutableQuery(@"
MERGE (p:Person {name: $name})
MERGE (friend:Person {name: $friendName})
MERGE (p)-[r:KNOWS {status: $status, since: date()}]->(friend)
RETURN r AS friendship
")
.WithParameters(new { name = "Alice", friendName = "Bob", status = "BFF" })
.WithConfig(new QueryConfig(database: "neo4j"))
.ExecuteAsync();
var relationship = result.Result[0].Get<IRelationship>("friendship");
Console.WriteLine($"Type: {relationship.Type}");
Console.WriteLine("Properties: {0}", string.Join(", ", relationship.Properties));
Console.WriteLine("Status property: {0}", relationship.Get<string>("status"));
/*
Type: KNOWS
Properties: [since, 2024-12-22], [status, BFF]
Status property: BFF
*/
For full documentation, see API documentation → IRelationship.
IPath
Represents a path in a graph.
using Neo4j.Driver;
const string dbUri = "<database-uri>";
const string dbUser = "<username>";
const string dbPassword = "<password>";
await using var driver = GraphDatabase.Driver(dbUri, AuthTokens.Basic(dbUser, dbPassword));
await driver.VerifyConnectivityAsync();
// Create some :Person nodes linked by :KNOWS relationships
await addFriend(driver, "Alice", "BFF", "Bob");
await addFriend(driver, "Bob", "Fiends", "Sofia");
await addFriend(driver, "Sofia", "Acquaintances", "Alice");
// Follow :KNOWS relationships outgoing from Alice three times, return as path
var result = await driver.ExecutableQuery(@"
MATCH path=(:Person {name: $name})-[:KNOWS*3]->(:Person)
RETURN path AS friendshipChain
")
.WithParameters(new { name = "Alice" })
.WithConfig(new QueryConfig(database: "neo4j"))
.ExecuteAsync();
// Extract path from result
var path = result.Result[0].Get<IPath>("friendshipChain");
Console.WriteLine("-- Path breakdown --");
for (var i=0; i<path.Relationships.Count; i++) {
Console.WriteLine("{0} knows {1} ({2}).",
path.Nodes[i].Get<string>("name"),
path.Nodes[i+1].Get<string>("name"),
path.Relationships[i].Get<string>("status")
);
}
/*
-- Path breakdown --
Alice knows Bob (BFF).
Bob knows Sofia (Fiends).
Sofia knows Sofia (Acquaintances).
*/
async Task addFriend(IDriver driver, string name, string status, string friendName) {
await driver.ExecutableQuery(@"
MERGE (p:Person {name: $name})
MERGE (friend:Person {name: $friendName})
MERGE (p)-[r:KNOWS {status: $status, since: date()}]->(friend)
")
.WithParameters(new { name = name, status = status, friendName = friendName })
.WithConfig(new QueryConfig(database: "neo4j"))
.ExecuteAsync();
}
For full documentation, see API documentation → IPath.
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
.ExecuteReadAsync()
or.ExecuteWriteAsync()
call. The driver automatically re-executes the callback in case of server failure. - IDriver
-
A
IDriver
object holds the details required to establish connections with a Neo4j database.