自定义、基于 Cypher 的过程和函数
所有这些过程(除了列表和显示过程)都打算在系统数据库中执行,因此它们必须通过打开系统数据库会话来执行。有几种方法可以做到这一点: - 当使用 cypher-shell 或 Neo4j 浏览器时,可以使用 `:use system` 前缀其 Cypher 查询 - 当使用 fabric 时,可以使用 `USE system` 前缀其 Cypher 查询 - 当使用驱动程序时,可以打开直接针对系统数据库的会话 此外,它们接受第一个参数作为我们想要安装/更新/删除自动 UUID 的数据库名称。通过这种实现,我们可以利用集群路由机制,在集群环境中使用这些过程。 |
安装、更新或删除自定义 Cypher 语句是最终一致的操作。因此,它们不会立即添加/更新/删除,但它们具有由 Apoc 配置 `apoc.custom.procedures.refresh=<MILLISECONDS>` 处理的刷新率。 在集群环境的情况下,`apoc.custom.procedures.refresh` 还将过程/函数复制到每个集群成员。 |
限定名称 | 类型 | 版本 |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
概述
我一直想要能够将 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
answer |
---|
42 |
或者也可以这样写
CALL apoc.custom.installProcedure('answer() :: (row::MAP)', 'RETURN 42 as answer')
在这种情况下,结果被包装在一个名为 `row` 的映射流中。因此,您可以执行
CALL custom.answer()
YIELD row
RETURN row.answer
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);
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()
answer |
---|
42 |
或者也可以这样写
CALL apoc.custom.installFunction('answerFunMap() :: MAP', 'RETURN 42 as answer')
在这种情况下,结果被包装在一个名为 `row` 的映射流中。因此,您可以执行
WITH custom.answerFunMap() YIELD row
RETURN row.answer
answer |
---|
42 |
我们可以通过运行以下函数创建函数 `custom.double`,它将提供的值加倍
CALL apoc.custom.installFunction(
'double(input::INT) :: INT',
'RETURN $input*2 as answer'
);
我们可以使用此函数,如下面的查询所示
RETURN custom.double(83) AS value;
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
);
value |
---|
1 |
否则,如果为 false,结果将是一个单例列表
CALL apoc.custom.installFunction('forceSingleFalse(input::ANY) :: LIST OF INT',
'RETURN 1',
false
);
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 存储过程。 |