Source: https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/fe/functions/user-defined/ Documentation version: v5.3.2 # 用户自定义函数(UDF) 本文介绍如何在悦数图数据库开发版中使用 GQL 创建和使用用户自定义函数(基于 GQL 的 UDF)。 ## 概述 您可以使用 GQL 表达式定义自定义函数,扩展悦数图数据库开发版的内置函数库。UDF 在查询中的调用方式与内置函数一致,便于复用复杂的计算逻辑。 ## 使用限制 - 仅支持定义类型为`scalar`和`aggregate`的函数。关于函数的类型,请参见 [SHOW FUNCTIONS](https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/data-admin/show/show-functions/)。 - 不支持子查询表达式。 - 不支持可变参数。 - 不支持在函数定义中调用任何 UDF。 - 不允许使用全局聚合值变量(如`@nodeAgg`)。 Note 对非默认 Schema 或其中的对象执行操作时,用户既要通过隐式访问规则或显式`USAGE`授权获得该 Schema 的访问权,也要具备目标操作所需的权限。Schema 访问校验和目标操作所需的权限校验相互独立,满足其中一项不能替代另一项。Schema 访问控制不适用于临时图、内置 Procedure 和内置 Function。更多信息,请参见 [Schema 访问控制](https://dev-docs.yueshu.com.cn/v5.3.2/server-admin/authorization/schema-access-control/)。 ## 前提条件 - 若要创建 UDF,必须具备在当前 Schema 执行`CREATE FUNCTION`权限。更多信息,请参见[角色与权限](https://dev-docs.yueshu.com.cn/v5.3.2/server-admin/authorization/)。 - 若要删除 UDF,必须是 UDF 的所有者,或具备在 UDF 上执行`DROP`权限;或具备在当前 Schema 执行`DROP ANY FUNCTION`操作权限。更多信息,请参见[角色与权限](https://dev-docs.yueshu.com.cn/v5.3.2/server-admin/authorization/)。 ## 语法 ### 创建 UDF 语法图源码 create_function_statement parameter_declaration ```` create_function_statement ::= 'CREATE' 'FUNCTION' ('IF NOT EXISTS')? function_name '(' (parameter_declaration (',' parameter_declaration)* )? ')' 'RETURNS' return_type 'AS' '{' expression '}' ('COMMENT' string_literal)? parameter_declaration ::= parameter_name parameter_type ```` #### `IF NOT EXISTS` 该子句用于检查是否已存在同名的 UDF。如果已存在,则不创建且不抛出异常。 如果不指定该子句,当同名 UDF 已存在时会抛出异常。 #### `function_name` 要创建的 UDF 名称。名称必须是合法的标识符,且不能与任何内置函数或已有的自定义函数名称冲突。有关标识符的命名规则,请参见[标识符命名规则](https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/overview/keywords-identifiers/)。 与 UDP 不同,UDF 不支持[函数重载](https://en.wikipedia.org/wiki/Function_overloading)。不能创建多个同名但参数不同的 UDF。 #### `parameter_declaration` UDF 的输入参数声明。每个参数由名称和数据类型组成。 #### `parameter_name` UDF 接受的输入参数名称。参数名在同一个 UDF 内必须唯一。 #### `parameter_type` UDF 接受的输入参数的数据类型,可以是任意数据类型。有关数据类型的信息,请参见[数据类型](https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/data-types/)。 #### `return_type` UDF 返回值的数据类型。 #### `COMMENT` UDF 的可选描述信息。使用字符串字面量说明函数用途。 #### `expression` 定义 UDF 逻辑的表达式。 ### 删除 UDF 语法图源码 drop_function_statement ```` drop_function_statement ::= 'DROP' 'FUNCTION' 'IF EXISTS'? function_name ```` #### `IF EXISTS` 该子句用于检查要删除的 UDF 是否存在。如果不存在,则不执行删除且不抛出异常。 如果不指定该子句,当 UDF 不存在时会抛出异常。 #### `function_name` 要删除的函数名称。 ### 查看 UDF 信息 语法图源码 show_functions_statement show_specific_function_statement ```` show_functions_statement ::= 'SHOW' 'GQL'? 'USER DEFINED' 'FUNCTIONS' show_specific_function_statement ::= 'SHOW' 'GQL'? 'USER DEFINED' 'FUNCTION' function_name ```` 更多信息,请参见 [SHOW USER DEFINED FUNCTIONS](https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/data-admin/show/show-user-defined-functions/)。 ## 示例 ### 创建无参数的 UDF ```` ''' -- 创建一个返回圆周率的函数 CREATE FUNCTION IF NOT EXISTS _pi() RETURNS FLOAT AS {3.1415926} ''' ''' -- 调用该函数 RETURN _pi() AS pi_value ''' ```` 返回: ```` +-----------+ | pi_value | +-----------+ | 3.1415926 | +-----------+ ```` ### 创建带参数的 UDF ```` ''' -- 创建一个计算两数之和的函数 CREATE FUNCTION IF NOT EXISTS foo(a INT, b FLOAT) RETURNS FLOAT AS {a + b} ''' ''' -- 调用该函数 RETURN foo(10, 5.5) AS result ''' ```` 返回: ```` +--------+ | result | +--------+ | 15.5 | +--------+ ```` ### 创建带注释的 UDF ```` ''' -- 创建带注释的函数 CREATE FUNCTION IF NOT EXISTS add_tax(price FLOAT) RETURNS FLOAT AS {price * 1.06} COMMENT '计算含税价格' ''' ''' -- 查看函数注释 SHOW USER DEFINED FUNCTION add_tax ''' ```` 返回: ```` +---------+------------------------------------------------+--------------+ | name | signature | comment | +---------+------------------------------------------------+--------------+ | add_tax | add_tax(price FLOAT) -> FLOAT { price * 1.06 } | 计算含税价格 | +---------+------------------------------------------------+--------------+ ```` ### 创建使用聚合函数的 UDF ```` ''' -- 在 UDF 中使用内置聚合函数 CREATE FUNCTION IF NOT EXISTS avg_sum(b FLOAT) RETURNS FLOAT AS {avg(b) + sum(abs(b))} ''' ''' -- 调用该函数 FOR pair IN [[1,2], [1,3], [2,3], [4,2]] RETURN pair[0] AS a, pair[1] AS b NEXT RETURN a, avg_sum(b) AS result GROUP BY a ''' ```` 返回: ```` +---+--------+ | a | result | +---+--------+ | 1 | 7.5 | | 2 | 6.0 | | 4 | 4.0 | +---+--------+ ```` ### 创建使用会话变量的 UDF UDF 可以引用会话变量: ```` ''' -- 设置会话变量 SESSION SET VALUE $offset = 10 ''' ''' -- 创建使用会话变量的函数 CREATE FUNCTION IF NOT EXISTS add_offset(x FLOAT) RETURNS FLOAT AS {x + $offset} ''' ''' -- 调用该函数 RETURN add_offset(5) AS result ''' ```` 返回: ```` +--------+ | result | +--------+ | 15 | +--------+ ```` ### 在复杂查询中使用 UDF 在查询中调用前面示例中创建的`foo()`和`_pi()`函数: 示例 1: ```` ''' FOR i IN [1, 2, 3, 4] RETURN i, foo(-i, _pi()) AS calculated_value ORDER BY foo(-i, _pi()) DESC ''' ```` 返回: ```` +---+------------------+ | i | calculated_value | +---+------------------+ | 1 | 2.1415926 | | 2 | 1.1415926 | | 3 | 0.1415926 | | 4 | -0.8584074 | +---+------------------+ ```` 示例 2: ```` ''' USE movie MATCH (v:Person WHERE v.id = foo(5, 10.0))-[e]->(n) RETURN v.id AS vid, n.id AS nid, n.name AS nname ORDER BY nname ''' ```` 返回: ```` +-----+-----+-------------------------------+ | vid | nid | nname | +-----+-----+-------------------------------+ | 15 | 644 | A.I. Artificial Intelligence | | 15 | 497 | Green Mile | | 15 | 377 | Nightmare on Elm Street | | 15 | 473 | Pi | | 15 | 129 | Sen To Chihiro No Kamikakushi | | 15 | 10 | Star Wars | | 15 | 11 | Star Wars: A New Hope | +-----+-----+-------------------------------+ ```` ### 查看 UDF 信息 有关查看 UDF 信息的方法,请参见 [SHOW USER DEFINED FUNCTIONS](https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/data-admin/show/show-user-defined-functions/)。 ### 删除 UDF ```` ''' -- 删除前面示例中创建的 foo() 函数 DROP FUNCTION foo -- 若存在则删除 DROP FUNCTION IF EXISTS foo ''' ````