数据类型及其与 Cypher 类型的映射

本节中的表格展示了 Cypher 数据类型与 .NET 类型之间的映射关系。

核心类型

Cypher 类型 驱动程序类型

NULL

null

LIST

IList<object>

MAP

IDictionary<string, object>

布尔值 (BOOLEAN)

bool

INTEGER(整数)

long

FLOAT

double

STRING

string

ByteArray

byte[]

时间类型

该驱动程序提供了一套符合 ISO-8601 标准和 Cypher 规范的时间数据类型。
亚秒级数值精确到纳秒。

时区名称遵循 IANA 系统,而非 Windows 系统
入站转换使用 Unicode CLDR 定义的 扩展 Windows-Olson zid 映射 进行。

Cypher 类型 驱动程序类型

DATE

LocalDate

ZONED TIME

OffsetTime

LOCAL TIME

LocalTime

ZONED DATETIME

ZonedDateTime

LOCAL DATETIME

LocalDateTime

DURATION(持续时间)

Duration

如何在查询中使用时间类型
// 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: "<database-name>"))
    .ExecuteAsync();

Console.WriteLine(result.Result[0].Get<ZonedDateTime>("date"));
// 2016-12-16T13:59:59.999000000[Europe/Stockholm]

空间类型

Cypher 支持空间值(点),Neo4j 可以将这些点值存储为节点和关系的属性。

属性 SRID空间参考标识符 的缩写)是一个用于标识空间类型解释坐标系统的数字。你可以将其视为每个空间类型的唯一标识符。

Cypher 类型 驱动程序类型 SRID

POINT (2D 笛卡尔坐标系)

Point

7203

POINT (2D WGS-84)

Point

4326

POINT (3D 笛卡尔坐标系)

Point

9157

POINT (3D WGS-84)

Point

4979

从数据库接收 Point
var result = await driver.ExecutableQuery("RETURN point({x: 2.3, y: 4.5, z: 2}) AS point")
    .WithConfig(new QueryConfig(database: "<database-name>"))
    .ExecuteAsync();
Console.WriteLine(result.Result[0].Get<Point>("point"));
// Point{srId=9157, x=2.3, y=4.5, z=2}
创建 Point 值并将其用作属性值
var 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: "<database-name>"))
    .ExecuteAsync();
Console.WriteLine(result.Result[0].Get<INode>("p").Get<Point>("location"));
// Point{srId=4326, x=67.28775180193841, y=17.734163823312397}

图类型

图类型仅作为结果传递,不可用作参数.

Cypher 类型 驱动程序类型

NODE

INode

RELATIONSHIP

IRelationship

PATH

IPath

INode

表示图中的一个节点。

表 1. 节点对象的基本成员
属性/方法 返回

标签

节点标签,以列表形式。

属性

节点属性,以映射形式。

Get<type>("<propertyName>")

给定属性的值,转换为 type 类型。

ElementId()

节点的字符串标识符。使用时需谨慎,因为无法保证 ID 值与单个事务范围之外的元素之间的映射关系。换句话说,使用 elementId 在不同事务之间执行 MATCH 操作是有风险的。

检索节点并显示其详细信息
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: "<database-name>"))
    .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
*/

有关完整文档,请参阅 API 文档 → INode

IRelationship

表示图中的一个关系。

表 2. 关系对象的基本成员
属性/方法 返回

类型

关系类型。

属性

关系属性,以映射形式。

Get<type>("<propertyName>")

给定属性的值,转换为 type 类型。

StartNodeElementId

起始节点的 elementId

EndNodeElementId

结束节点的 elementId

ElementId

关系的字符串标识符。使用时需谨慎,因为无法保证 ID 值与单个事务范围之外的元素之间的映射关系。换句话说,使用 elementId 在不同事务之间执行 MATCH 操作是有风险的。

检索关系并显示其详细信息
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: "<database-name>"))
    .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
*/

有关完整文档,请参阅 API 文档 → IRelationship

IPath

表示图中的一条路径。

检索路径并遍历
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: "<database-name>"))
    .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: "<database-name>"))
        .ExecuteAsync();
}

有关完整文档,请参阅 API 文档 → IPath

Vector

类型 Vector 映射到 Cypher 类型 VECTOR。Vector 对象存储为包含同质值的连续内存块。你可以根据 floatdoublesbyteshortintlong 的列表来创建向量。

在数据库中存储 VECTOR 对象需要服务器版本 >= 2025.10,企业版。
创建并存储向量
var vector = new Vector<int>([5, 6, 7]);
var result = await driver.ExecutableQuery("MERGE (d:Doc {embedding: $vector})")
    .WithParameters(new { vector = vector })
    .WithConfig(new QueryConfig(database: "<database-name>"))
    .ExecuteAsync();

UnsupportedType

类型 UnsupportedType 用于驱动程序无法识别的 Cypher 查询返回的数据类型。当客户端版本相对于服务器版本过旧时,会出现这种情况。

术语表

LTS (长期支持版)

长期支持 (Long Term Support) 版本是保证在若干年内得到支持的版本。Neo4j 4.4 和 5.26 是 LTS 版本。

Aura

Aura 是 Neo4j 的全托管云服务。它提供免费和付费计划。

Cypher

Cypher 是 Neo4j 的图查询语言,允许您从数据库中检索数据。它就像 SQL,但专用于图数据库。

APOC

Awesome Procedures On Cypher (APOC) 是一个包含(许多)函数的库,这些函数在 Cypher 本身中难以轻松实现。

Bolt

Bolt 是用于 Neo4j 实例和驱动程序之间交互的协议。默认监听 7687 端口。

ACID

原子性 (Atomicity)、一致性 (Consistency)、隔离性 (Isolation)、持久性 (Durability) (ACID) 是保证数据库事务可靠处理的属性。符合 ACID 的 DBMS 确保即使发生故障,数据库中的数据也能保持准确和一致。

最终一致性

如果一个数据库能保证所有集群成员在某个时间点都存储了数据的最新版本,则该数据库具有最终一致性。

因果一致性

如果读写查询被集群中的每个成员以相同的顺序看到,则数据库具有因果一致性。这比最终一致性更强。

NULL

空标记不是一种类型,而是缺失值的占位符。更多信息,请参阅 Cypher → 使用 null

事务

事务是一个工作单元,要么被提交,要么在失败时被回滚。例如银行转账:它涉及多个步骤,但它们必须全部成功或全部撤销,以避免钱从一个账户扣除却未存入另一个账户的情况。

背压

背压是对数据流的抵抗力。它确保客户端不会被过快发送的数据压垮,从而超出其处理能力。

书签

书签是代表数据库某种状态的标记。通过将一个或多个书签与查询一起传递,服务器将确保在所表示的状态建立之前,该查询不会被执行。

事务函数

事务函数是由 .ExecuteReadAsync().ExecuteWriteAsync() 调用执行的回调。如果服务器发生故障,驱动程序会自动重新执行回调。

IDriver

IDriver 对象保存了与 Neo4j 数据库建立连接所需的详细信息。