跳转至
开发版采用单机部署,无需产品 License 文件。需要多机部署或大规模性能测试? 了解企业版

用户自定义函数(UDF)

本文介绍如何在悦数图数据库开发版中使用 GQL 创建和使用用户自定义函数(基于 GQL 的 UDF)。

概述

您可以使用 GQL 表达式定义自定义函数,扩展悦数图数据库开发版的内置函数库。UDF 在查询中的调用方式与内置函数一致,便于复用复杂的计算逻辑。

使用限制

  • 仅支持定义类型为scalar和aggregate的函数。关于函数的类型,请参见 SHOW FUNCTIONS。
  • 不支持子查询表达式。
  • 不支持可变参数。
  • 不支持在函数定义中调用任何 UDF。
  • 不允许使用全局聚合值变量(如@nodeAgg)。

Note

对非默认 Schema 或其中的对象执行操作时,用户既要通过隐式访问规则或显式USAGE授权获得该 Schema 的访问权,也要具备目标操作所需的权限。Schema 访问校验和目标操作所需的权限校验相互独立,满足其中一项不能替代另一项。Schema 访问控制不适用于临时图、内置 Procedure 和内置 Function。更多信息,请参见 Schema 访问控制。

前提条件

  • 若要创建 UDF,必须具备在当前 Schema 执行CREATE FUNCTION权限。更多信息,请参见角色与权限。
  • 若要删除 UDF,必须是 UDF 的所有者,或具备在 UDF 上执行DROP权限;或具备在当前 Schema 执行DROP ANY FUNCTION操作权限。更多信息,请参见角色与权限。

语法

创建 UDF

create_function_statement
CREATE FUNCTION IF NOT EXISTS function_name ( parameter_declaration , ) RETURNS return_type AS { expression } COMMENT string_literal
parameter_declaration
parameter_name parameter_type

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 名称。名称必须是合法的标识符,且不能与任何内置函数或已有的自定义函数名称冲突。有关标识符的命名规则,请参见标识符命名规则。

与 UDP 不同,UDF 不支持函数重载。不能创建多个同名但参数不同的 UDF。

parameter_declaration

UDF 的输入参数声明。每个参数由名称和数据类型组成。

parameter_name

UDF 接受的输入参数名称。参数名在同一个 UDF 内必须唯一。

parameter_type

UDF 接受的输入参数的数据类型,可以是任意数据类型。有关数据类型的信息,请参见数据类型。

return_type

UDF 返回值的数据类型。

COMMENT

UDF 的可选描述信息。使用字符串字面量说明函数用途。

expression

定义 UDF 逻辑的表达式。

删除 UDF

drop_function_statement
DROP FUNCTION IF EXISTS function_name

drop_function_statement ::=
'DROP' 'FUNCTION' 'IF EXISTS'? function_name

IF EXISTS

该子句用于检查要删除的 UDF 是否存在。如果不存在,则不执行删除且不抛出异常。

如果不指定该子句,当 UDF 不存在时会抛出异常。

function_name

要删除的函数名称。

查看 UDF 信息

show_functions_statement
SHOW GQL USER DEFINED FUNCTIONS
show_specific_function_statement
SHOW GQL USER DEFINED FUNCTION function_name

show_functions_statement ::= 
    'SHOW' 'GQL'? 'USER DEFINED' 'FUNCTIONS' 
show_specific_function_statement ::= 
    'SHOW' 'GQL'? 'USER DEFINED' 'FUNCTION' function_name

更多信息,请参见 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。

删除 UDF

'''
-- 删除前面示例中创建的 foo() 函数
DROP FUNCTION foo

-- 若存在则删除
DROP FUNCTION IF EXISTS foo
'''