Apache Arrow 投影
通过 Apache Arrow 进行图投影,允许导入存储在 Neo4j 之外的图数据。Apache Arrow 是一种与语言无关的内存中列式数据结构规范。利用 Arrow Flight,它还包含了一套用于序列化和通用数据传输的协议。
GDS 提供了一个 Arrow Flight 服务器,可接收来自 Arrow Flight 客户端的图数据。传输的数据使用 Arrow 列式格式表示。通过 Arrow Flight 进行图投影遵循特定的客户端-服务器协议。在本章中,我们将解释该协议、消息格式以及模式限制。
在本章中,我们假设 Flight 服务器已经完成安装和配置。如需了解更多安装相关信息,请参考 安装章节。
图投影功能采用版本控制,以便进行未来变更。有关版本化命令的更多详细信息,请参考 配置 Apache Arrow 服务器 文档中的 相应章节。
客户端-服务器协议
该协议描述了将单个内存中图投影到 GDS 的过程。每个投影在服务器端都表现为一个导入流程。协议将导入流程分为三个阶段。
-
初始化导入流程
为了初始化导入流程,客户端需要在服务器上执行一个 Flight 操作。该操作类型称为
CREATE_GRAPH,操作体用于配置导入流程。服务器接收该操作,创建导入流程并确认成功。详情请参见 初始化导入流程。
-
通过 Arrow Flight 流发送节点记录
在第二阶段,客户端通过
PUT以 Flight 流的形式发送节点记录批次。一旦所有记录批次发送完毕,客户端需要指明所有节点已发送完成。这通过发送另一个类型为NODE_LOAD_DONE的 Flight 操作来完成。详情请参见 通过 PUT 以 Flight 流的形式发送节点记录。
-
通过 Arrow Flight 流发送关系记录
在第三个也是最后一个阶段,客户端通过
PUT以 Flight 流的形式发送关系记录批次。一旦所有记录批次发送完毕,客户端需要指明导入流程已完成。这通过发送另一个类型为RELATIONSHIP_LOAD_DONE的 Flight 操作来完成。服务器将完成内存中图的构建,并将该图存储在图目录中。详情请参见 通过 PUT 以 Flight 流的形式发送关系记录。
初始化导入流程
导入流程通过发送类型为 v1/CREATE_GRAPH 的 Flight 操作来初始化。操作类型包含服务器版本,目前为版本 1 (v1)。操作体是一个包含导入流程元数据的 JSON 文档:
{
name: "my_graph", (1)
database_name: "neo4j", (2)
concurrency: 4, (3)
undirected_relationship_types: [] (4)
inverse_indexed_relationship_types: [] (5)
skip_dangling_relationships: false (6)
}
| 1 | 用于标识导入流程。它也是图目录中生成的内存中图的名称。 |
| 2 | 将提供该投影图的数据库名称。 |
| 3 | (可选)接收所有数据后,将在内存中图上设置的并发级别。 |
| 4 | (可选)必须作为无向关系导入的关系类型列表。可以使用通配符 (*) 包含所有类型。 |
| 5 | (可选)必须按反向建立索引的关系类型列表。可以使用通配符 (*) 包含所有类型。 |
| 6 | (可选)如果设置为 true,则在导入过程中将跳过悬空关系。否则,如果检测到悬空关系,导入过程将失败。 |
| 声明为无向的关系应仅提供一次,即仅沿一个方向提供。 |
服务器通过发送包含导入流程名称的结果 JSON 文档来确认创建导入流程。如果发生错误(例如,图已存在或服务器未启动),客户端将收到相应通知。
通过 PUT 以 Flight 流的形式发送节点记录
节点需要转换为 Arrow 记录批次,并通过 Flight 流发送到服务器。每个流都需要指向服务器上的某个导入流程。该信息作为 JSON 文档编码在 Flight 描述符主体中:
{
name: "PUT_COMMAND",
version: "v1",
body: {
name: "my_graph",
entity_type: "node",
}
}
服务器要求节点记录必须符合特定模式。以示例节点 (:Pokemon { weight: 8.5, height: 0.6, hp: 39 }) 为例,其记录必须按以下方式表示:
| nodeId | 标签 | weight | height | hp |
|---|---|---|---|---|
0 |
"Pokemon" |
8.5 |
0.6 |
39 |
下表描述了具有保留名称的节点列:
| 名称 | 类型 | 可选 | 可为空 | 描述 |
|---|---|---|---|---|
|
整数 |
否 |
否 |
内存中图的唯一 64 位节点标识符。必须为正值。 |
|
字符串、整数或字符串列表 |
是 |
否 |
节点标签,可以是单个字符串节点标签、单个字典编码的节点标签或节点标签字符串列表。 |
任何其他列都被解释为节点属性。支持的数据类型等同于 GDS 节点属性类型,即 long、double、long[]、double[] 和 float[]。
对于浮点值,null 将转换为 NaN。 |
为了提高吞吐量,可以并行发送多个 Flight 流。服务器负责管理同一导入流程的多个传入流。除了并行流的数量外,单个记录批次的大小也会影响整体吞吐量。客户端必须确保节点 ID 在所有流中是唯一的。
| 发送重复的节点 ID 将导致未定义的行为。 |
一旦所有节点记录批次都发送到服务器,客户端需要指明节点加载已完成。这可以通过发送另一个类型为 v1/NODE_LOAD_DONE 的 Flight 操作并附带以下 JSON 文档作为操作体来实现:
{
name: "my_graph"
}
服务器通过返回一个 JSON 文档来确认该操作,其中包含导入流程的名称和已导入的节点数量。
{
name: "my_graph",
node_count: 42
}
通过 PUT 以 Flight 流的形式发送关系记录
与节点类似,关系需要转换为记录批次,以便通过 Flight 流发送到服务器。Flight 描述符是一个包含导入流程名称以及实体类型的 JSON 文档:
{
name: "PUT_COMMAND",
version: "v1",
body: {
name: "my_graph",
entity_type: "relationship",
}
}
与节点一样,服务器要求关系记录必须符合特定模式。例如,给定关系 (a)-[:EVOLVES_TO { at_level: 16 }]→(b),假设 a 的节点 ID 为 0,b 的节点 ID 为 1,则记录必须按以下方式表示:
| sourceNodeId | targetNodeId | type | at_level |
|---|---|---|---|
0 |
1 |
"EVOLVES_TO" |
16 |
下表描述了具有保留名称的节点列:
| 名称 | 类型 | 可选 | 可为空 | 描述 |
|---|---|---|---|---|
|
整数 |
否 |
否 |
唯一的 64 位源节点标识符。必须为正值且存在于已导入的节点中。 |
|
整数 |
否 |
否 |
唯一的 64 位目标节点标识符。必须为正值且存在于已导入的节点中。 |
|
字符串或整数 |
是 |
否 |
单一关系类型。可以是字符串字面量或字典编码的数字。 |
任何其他列都被解释为关系属性。GDS 仅支持 double 类型的关系属性。
与发送节点类似,整体吞吐量取决于并行 Flight 流的数量和记录批次大小。
一旦所有关系记录批次都发送到服务器,客户端需要指明导入流程已完成。这通过发送最后一个类型为 v1/RELATIONSHIP_LOAD_DONE 的 Flight 操作并附带以下 JSON 文档作为操作体来实现:
{
name: "my_graph"
}
服务器完成图投影并将内存中图存储在图目录中。完成后,服务器通过返回一个包含导入流程名称和已导入关系数量的 JSON 文档来确认该操作。
{
name: "my_graph",
relationship_count: 1337
}
中止导入流程
可以通过发送类型为 v1/ABORT 的 Flight 操作来中止已启动的导入流程。这将立即取消正在运行的图或数据库导入进程,并删除所有临时数据。
操作体是一个包含正在导入的图或数据库名称的 JSON 文档:
{
name: "my_graph",
}
|
如果在此期间未收到数据或指令,且超过可配置的超时时间,Arrow 导入流程将自动中止。超时可以通过 |
将新数据追加到现有图中
一旦创建了图,就可以将额外数据追加到现有图中。这避免了删除图并重新导入所有数据。该过程与初始导入过程类似,但有一些区别。
追加新节点属性
一旦创建了图,就可以将额外的节点属性追加到现有图中。为此,客户端需要发送与现有节点具有相同节点 ID 的节点记录。服务器将使用新属性更新现有节点,并可能限制为一组特定的节点标签。节点记录由 nodeId 列标识,该列在所有节点记录中必须是唯一的,并且必须与现有节点的节点 ID 匹配。
不需要为现有图中的所有节点发送节点属性值。如果新数据中未表示某条节点记录,则该记录将接收该属性类型的默认值。
如果属性已存在,或者提供的某个节点 ID 与现有节点不匹配,该过程将失败。
导入流程通过发送类型为 v1/PUT_NODE_PROPERTIES 的 Flight 操作并附带以下操作体来初始化:
{
name: "my_graph", (1)
database_name: "neo4j", (2)
concurrency: 4, (3)
node_labels: ["*"], (4)
consecutive_ids: false (5)
}
| 1 | 现有内存中图的名称。它也用于标识导入流程。 |
| 2 | 投影图所在的数据库名称。 |
| 3 | (可选)用于在服务器上构建属性数据结构的并发级别。 |
| 4 | (可选)将使用新属性更新的一组节点标签。可以使用通配符 (*) 包含所有标签。 |
| 5 | (可选)如果数据与已使用连续节点 ID 导出的图相关联,请将其设置为 true。 |
节点属性需要转换为 Arrow 记录批次,并通过 Flight 流发送到服务器。每个流都需要指向服务器上的导入流程。该信息作为 JSON 文档编码在 Flight 描述符主体中:
{
name: "PUT_COMMAND",
version: "v1",
body: {
name: "my_graph",
entity_type: "node_properties",
}
}
与发送节点和关系一样,整体吞吐量取决于并行 Flight 流的数量和记录批次大小。
与节点导入类似,服务器要求节点记录必须符合特定模式。以示例节点 ({ yob: 1984, magic: 1.8, rank: 42 }) 为例,其记录必须按以下方式表示:
| nodeId | yob | magic | rank |
|---|---|---|---|
0 |
1984 |
1.8 |
42 |
下表描述了具有保留名称的节点列:
| 名称 | 类型 | 可选 | 可为空 | 描述 |
|---|---|---|---|---|
|
整数 |
否 |
否 |
内存中图的唯一 64 位节点标识符。必须为正值。 |
除 nodeId 之外的任何额外列都被解释为要追加的新节点属性。支持的数据类型等同于 GDS 节点属性类型,即 long、double、long[]、double[] 和 float[]。
一旦所有节点记录批次都发送到服务器,客户端需要指明节点追加已完成。这通过发送另一个类型为 v1/PUT_NODE_PROPERTIES_DONE 的 Flight 操作并附带以下 JSON 文档作为操作体来实现:
{
name: "my_graph"
}
服务器通过返回一个包含导入流程名称和已更新节点数量的 JSON 文档来确认该操作。
{
name: "my_graph",
node_count: 1
}
创建 Neo4j 数据库
| 此功能在 AuraDS 中不可用。 |
客户端-服务器协议也可以用于创建新的 Neo4j 数据库,而不是内存中图。要初始化数据库导入流程,我们需要将初始操作类型更改为 v1/CREATE_DATABASE。操作体是一个包含导入流程配置的 JSON 文档:
{
name: "my_database",
concurrency: 4
}
下表包含数据库导入的所有设置:
| 名称 | 类型 | 可选 | 默认值 | 描述 |
|---|---|---|---|---|
|
字符串 |
否 |
None |
导入流程的名称和生成的数据库名称。 |
|
字符串 |
是 |
INTEGER(整数) |
设置输入数据中使用的节点 ID 类型。可以是 |
|
整数 |
是 |
可用核心数 |
用于数据库创建过程的线程数。 |
|
字符串 |
是 |
|
存储输入数据节点 ID 的节点属性键。 |
|
字符串 |
是 |
|
已弃用:请改用 |
|
字符串 |
是 |
|
数据库格式。有效值为空(无值,默认)、 |
|
布尔值 |
是 |
False |
强制在导入前删除任何现有的数据库文件。 |
|
布尔值 |
是 |
False |
忽略基于环境的启发式方法,并指定目标存储子系统是否可以支持高吞吐量的并行 IO。 |
|
布尔值 |
是 |
False |
在导入过程中收集错误的节点和关系记录并将它们写入日志。 |
在发送用于初始化导入流程的操作后,后续协议与创建内存中图的协议相同。详情请参阅 通过 PUT 以 Flight 流的形式发送节点记录 和 通过 PUT 以 Flight 流的形式发送关系记录。