自定义、基于 Cypher 的过程和函数

所有这些过程(除了列表和显示过程)都打算在系统数据库中执行,因此它们必须通过打开系统数据库会话来执行。有几种方法可以做到这一点: - 当使用 cypher-shell 或 Neo4j 浏览器时,可以使用 `:use system` 前缀其 Cypher 查询 - 当使用 fabric 时,可以使用 `USE system` 前缀其 Cypher 查询 - 当使用驱动程序时,可以打开直接针对系统数据库的会话

此外,它们接受第一个参数作为我们想要安装/更新/删除自动 UUID 的数据库名称。通过这种实现,我们可以利用集群路由机制,在集群环境中使用这些过程。

安装、更新或删除自定义 Cypher 语句是最终一致的操作。因此,它们不会立即添加/更新/删除,但它们具有由 Apoc 配置 `apoc.custom.procedures.refresh=<MILLISECONDS>` 处理的刷新率。

在集群环境的情况下,`apoc.custom.procedures.refresh` 还将过程/函数复制到每个集群成员。

表 1. 可用过程
限定名称 类型 版本

apoc.custom.dropAll

apoc.custom.dropAll() - 最终删除所有先前添加的自定义过程/函数并返回信息

过程

Apoc 扩展

apoc.custom.dropFunction

apoc.custom.dropFunction() - 最终删除目标自定义函数

过程

Apoc 扩展

apoc.custom.dropProcedure

apoc.custom.dropProcedure() - 最终删除目标自定义过程

过程

Apoc 扩展

apoc.custom.installFunction

apoc.custom.installFunction() - 最终注册自定义 Cypher 函数

过程

Apoc 扩展

apoc.custom.installProcedure

apoc.custom.installProcedure() - 最终注册自定义 Cypher 过程

过程

Apoc 扩展

apoc.custom.list

apoc.custom.list() - 提供注册的自定义过程/函数列表

过程

Apoc 扩展

apoc.custom.show

apoc.custom.show() - 提供注册的自定义过程/函数列表

过程

Apoc 扩展

概述

我一直想要能够将 Cypher 语句注册为正式的存储过程和函数,这样它们就可以独立调用。

您可以使用 `apoc.custom.installProcedure` 和 `apoc.custom.installFunction` 存储过程调用来实现这一点。这些会注册给定的 Cypher 语句,并在前面加上 `custom.*` 命名空间,覆盖可能已存在的语句,因此您可以根据需要重新定义它们。

`apoc.custom.installProcedure` 和 `apoc.custom.installFunction` 存储过程的第一个参数是您要创建的存储过程/函数的签名。

这与 `SHOW PROCEDURES YIELD signature`、`SHOW FUNCTIONS YIELD signature` Cypher 命令或 `CALL apoc.help('<fun_or_procedure_name>') YIELD signature` 存储过程返回的 `signature` 结果类似,只是没有 `?`。也就是说: - 对于存储过程:`nameProcedure(firstParam = defaultValue :: typeParam , secondParam = defaultValue :: typeParam, …​.) :: (firstResult :: typeResult, secondResult :: typeResult, …​ )` - 对于函数:`nameFunction(firstParam = defaultValue :: typeParam , secondParam = defaultValue :: typeParam, …​.) :: typeResult`

请注意,对于存储过程和函数,`= defaultValue` 是可选的。默认值被解析为 JSON。

如果您想要创建一个带有默认 `String` 参数的存储过程/函数,该参数包含空格、引号(例如: `"my text ' with ' quote"`)或 `"null"`(作为字符串),您需要引用结果,例如 `CALL apoc.custom.declareProcedure("procWithNullString(param='null'::STRING)::(output::STRING)", 'return $param as output')`
类型名称

签名参数中的 `typeParam` 和 `typeResult` 可以是以下值之一

  • FLOAT,DOUBLE,INT,INTEGER,INTEGER | FLOAT,NUMBER,LONG

  • TEXT,STRING

  • BOOL,BOOLEAN

  • POINT,GEO,GEOMETRY

  • DATE,DATETIME,LOCALDATETIME,TIME,LOCALTIME,DURATION

  • NODE,REL,RELATIONSHIP,EDGE,PATH

  • MAP

  • MAPRESULT(对 declareFunction 有效,不会将结果包装在另一个映射中。参见: [map-vs-map-result]

  • LIST TYPE,LIST OF TYPE(其中 `TYPE` 可以是前面的值之一)

  • ANY

在 Neo4j 5.13 中,`NUMBER` 类型被替换为 `INTEGER | FLOAT`,但我们仍然可以为了向后兼容而使用它。
如果您覆盖了存储过程或函数,您可能需要调用 `call db.clearQueryCaches()`,因为内部 ID 的查找会保存在已编译的查询计划中。

从 5.11 版本开始,如果我们执行 `CALL apoc.custom.installFunction('nameFun(…​.)')` 或 `CALL apoc.custom.installProcedure('nameProc(…​.)')`,我们不能在同一个事务中分别执行 `RETURN custom.nameFun(..) ` 或 `CALL custom.nameProc()`,否则会抛出错误。

因此,我们必须打开一个新事务来执行声明的自定义存储过程/函数。

以下示例假设我们位于 `neo4j` 数据库,我们想在该数据库中创建自定义存储过程/函数。

使用 `apoc.custom.installProcedure` 创建自定义存储过程

存储过程、输入和输出名称必须至少包含 2 个字符。

以下是一个简单的示例

CALL apoc.custom.installProcedure('answerInteger() :: (answer::INT)', 'RETURN 42 as answer')

这会在 **由配置 `apoc.custom.procedures.refresh` 定义的时间之后** 注册一个存储过程 `custom.answer`,然后您可以调用它。

CALL custom.answerInteger
表 2. 结果
answer

42

或者也可以这样写

CALL apoc.custom.installProcedure('answer() :: (row::MAP)', 'RETURN 42 as answer')

在这种情况下,结果被包装在一个名为 `row` 的映射流中。因此,您可以执行

CALL custom.answer()
YIELD row
RETURN row.answer
表 3. 结果
answer

42

我们可以创建存储过程 `custom.powers`,它返回第一个参数的幂的流,直到并包括第二个参数提供的幂

CALL apoc.custom.installProcedure(
  'powers(input::INT, power::INT) :: (answer::INT)',
  'UNWIND range(0, $power) AS power
   RETURN $input ^ power AS answer'
);

我们可以使用此函数返回 4°、4¹、4² 和 4³,如下面的查询所示

CALL custom.powers(4,3);
表 4. 结果
answer

1.0

4.0

16.0

64.0

此外,通过第三个参数,我们可以在与 `neo4j` 不同的数据库中创建自定义存储过程。例如,以下示例在 `foo` 数据库中创建一个自定义存储过程

CALL apoc.custom.installProcedure('foodb() :: (row::INT)', 'RETURN 42 as row', 'foo')

此外,我们可以将一个字符串作为第四个参数传递以指定存储过程模式(默认值为 "WRITE")。它可以是: - "READ" - 如果存储过程只会对图执行读取操作 - "WRITE" - 如果它可能对图执行读取和写入操作 - "SCHEMA" - 如果它将对模式执行操作 - "DBMS" - 如果它将执行系统操作 - 即,不针对图

此外,我们可以将 `description` 参数作为第五个参数传递,它将由 `call apoc.custom.list` 和 `SHOW PROCEDURES` 返回。

使用 `apoc.custom.installFunction` 创建自定义函数

函数、输入和输出名称必须至少包含 2 个字符。

以下是一个简单的示例

CALL apoc.custom.installFunction('answerFun() :: INT', 'RETURN 42 as answer')

这会在 **由配置 `apoc.custom.procedures.refresh` 定义的时间之后** 注册该语句作为存储过程 `custom.answer`,然后您可以调用它。

RETURN custom.answerFun()
表 5. 结果
answer

42

或者也可以这样写

CALL apoc.custom.installFunction('answerFunMap() :: MAP', 'RETURN 42 as answer')

在这种情况下,结果被包装在一个名为 `row` 的映射流中。因此,您可以执行

WITH custom.answerFunMap() YIELD row
RETURN row.answer
表 6. 结果
answer

42

我们可以通过运行以下函数创建函数 `custom.double`,它将提供的值加倍

CALL apoc.custom.installFunction(
  'double(input::INT) :: INT',
  'RETURN $input*2 as answer'
);

我们可以使用此函数,如下面的查询所示

RETURN custom.double(83) AS value;
表 7. 结果
value

166

此外,通过第三个参数,我们可以在与 `neo4j` 不同的数据库中创建自定义存储过程。例如,以下示例在 `foo` 数据库中创建一个自定义存储过程

CALL apoc.custom.installFunction('foodb() :: INT', 'RETURN 42', 'foo')

此外,我们可以将一个布尔值(默认值为 false)作为第四个参数传递,如果为 true,则如果函数返回单个元素的列表,它将只返回单个元素本身,而不是列表。

例如

CALL apoc.custom.installFunction('forceSingleTrue(input::ANY) :: LIST OF INT',
  'RETURN 1',
  true
);
表 8. 结果
value

1

否则,如果为 false,结果将是一个单例列表

CALL apoc.custom.installFunction('forceSingleFalse(input::ANY) :: LIST OF INT',
  'RETURN 1',
  false
);
表 9. 结果
value

[1]

此外,我们可以将 `description` 参数作为第五个参数传递,它将由 `call apoc.custom.list` 和 `SHOW FUNCTIONS` 返回。

使用 `apoc.custom.list` 列出已注册的存储过程/函数

存储过程 `apoc.custom.list` 通过 `apoc.custom.installProcedure` 和 `apoc.custom.installFunction` 提供已注册的所有存储过程/函数的列表

给定此调用

CALL apoc.custom.list

输出将类似于以下表格

type name description mode statement inputs outputs forceSingle

"function"

"answer"

<null>

<null>

"RETURN $input as answer"

[["input","integer | float"]]

"long"

false

"procedure"

"answer"

"Procedure that answer to the Ultimate Question of Life, the Universe, and Everything"

"read"

"RETURN $input as answer"

[["input","int","42"]]

[["answer","integer | float"]]

<null>

删除存储过程 `apoc.custom.dropProcedure`

存储过程 `apoc.custom.dropProcedure` 允许从特定数据库(默认值为 `neo4j`)中删除目标自定义存储过程,**由配置 `apoc.custom.procedures.refresh` 定义的时间之后**。

给定此调用

CALL apoc.custom.dropProcedure(<name>, <databaseName>)

字段

argument description

name

存储过程名称

databaseName

数据库名称(默认值:`neo4j`)

删除存储过程 `apoc.custom.dropFunction`

存储过程 `apoc.custom.dropFunction` 允许从特定数据库(默认值为 `neo4j`)中删除目标自定义函数,**由配置 `apoc.custom.procedures.refresh` 定义的时间之后**。

给定此调用

CALL apoc.custom.dropFunction(<name>)

字段

argument description

name

函数名称

databaseName

数据库名称(默认值:`neo4j`)

导出元数据

要将自定义存储过程导入到另一个数据库(例如在 `./neo4j-admin backup` 和 `/neo4j-admin restore` 之后),请参见 apoc.systemdb.export.metadata 存储过程。