Cassandra 文档

版本

您正在查看预发布版本的文档。

函数

CQL 支持两大类函数

在这两种情况下,CQL 都提供了一些本地的“硬编码”函数,以及创建新的用户定义函数的能力。

默认情况下,出于安全考虑,用户定义函数默认情况下是禁用的(即使启用,用户定义函数的执行也是沙盒化的,并且“恶意”函数不应该被允许做坏事,但没有沙盒是完美的,因此使用用户定义函数是选择加入的)。请参阅 cassandra.yaml 中的 user_defined_functions_enabled 以启用它们。

函数由其名称标识

function_name ::= [ keyspace_name'.' ] name

标量函数

原生函数

强制转换

cast 函数可用于将一种原生数据类型转换为另一种数据类型。

下表描述了 cast 函数支持的转换。Cassandra 会静默忽略将数据类型转换为其自身数据类型的任何强制转换。

ascii

text, varchar

bigint

tinyint, smallint, int, float, double, decimal, varint, text, varchar

boolean

text, varchar

counter

tinyint, smallint, int, bigint, float, double, decimal, varint, text, varchar

date

timestamp

decimal

tinyint, smallint, int, bigint, float, double, varint, text, varchar

double

tinyint, smallint, int, bigint, float, decimal, varint, text, varchar

float

tinyint, smallint, int, bigint, double, decimal, varint, text, varchar

inet

text, varchar

int

tinyint, smallint, bigint, float, double, decimal, varint, text, varchar

smallint

tinyint, int, bigint, float, double, decimal, varint, text, varchar

time

text, varchar

timestamp

date, text, varchar

timeuuid

timestamp, date, text, varchar

tinyint

tinyint, smallint, int, bigint, float, double, decimal, varint, text, varchar

uuid

text, varchar

varint

tinyint, smallint, int, bigint, float, double, decimal, text, varchar

转换严格依赖于 Java 的语义。例如,双精度值 1 将转换为文本值 '1.0'。例如

SELECT avg(cast(count as double)) FROM myTable

令牌

token 函数计算给定分区键的令牌。令牌函数的确切签名取决于所关注的表和集群使用的分区器。

token 的参数类型取决于分区键列类型。返回类型取决于定义的分区器

分区器 返回类型

Murmur3Partitioner

bigint

RandomPartitioner

varint

ByteOrderedPartitioner

blob

例如,考虑以下表

CREATE TABLE users (
    userid text PRIMARY KEY,
    username text,
);

该表使用默认的 Murmur3Partitioner。token 函数使用单个参数 text,因为分区键是 userid,类型为 text。返回类型将为 bigint

Uuid

uuid 函数不接受任何参数,并生成一个随机的类型 4 uuid,适合在 INSERTUPDATE 语句中使用。

Timeuuid 函数

now

now 函数不接受任何参数,并在协调器节点上生成一个新的唯一 timeuuid,时间为函数被调用时的时间。请注意,此方法对于插入很有用,但在 WHERE 子句中基本上没有意义。

例如,以下形式的查询

SELECT * FROM myTable WHERE t = now();

将不会返回结果,因为设计使然,因为 now() 返回的值保证是唯一的。

current_timeuuidnow 的别名。

min_timeuuidmax_timeuuid

min_timeuuid 函数接受一个 timestampt,可以是时间戳或日期字符串。它返回一个timeuuid,对应于时间戳 t最小可能 timeuuidmax_timeuuid 的工作原理类似,但返回最大可能 timeuuid

例如

SELECT * FROM myTable
 WHERE t > max_timeuuid('2013-01-01 00:05+0000')
   AND t < min_timeuuid('2013-02-02 10:00+0000');

将选择 timeuuidt'2013-01-01 00:05+0000' 之后且在 '2013-02-02 10:00+0000' 之前的所有行。子句 t >= maxTimeuuid('2013-01-01 00:05+0000') 仍然不会选择在 '2013-01-01 00:05+0000' 处生成的 timeuuid,并且本质上等效于 t > maxTimeuuid('2013-01-01 00:05+0000')

min_timeuuidmax_timeuuid 生成的值被称为 UUID,因为它们不遵守 IETF RFC 4122 指定的基于时间的 UUID 生成过程。特别是,这两种方法返回的值将不会是唯一的。因此,只将这些方法用于查询,而不是用于插入,以防止可能的数据覆盖。

日期时间函数

检索当前日期/时间

以下函数可用于检索函数被调用时的日期/时间

函数名称 输出类型

current_timestamp

timestamp

current_date

date

current_time

time

current_timeuuid

timeUUID

例如,可以使用以下方法检索过去两天的数据

SELECT * FROM myTable WHERE date >= current_date() - 2d;
时间转换函数

提供了一些函数,用于将 timeuuidtimestampdate 转换为其他 native 类型。

函数名称 输入类型 描述

to_date

timeuuid

timeuuid 参数转换为 date 类型

to_date

timestamp

timestamp 参数转换为 date 类型

to_timestamp

timeuuid

timeuuid 参数转换为 timestamp 类型

to_timestamp

date

date 参数转换为 timestamp 类型

to_unix_timestamp

timeuuid

timeuuid 参数转换为 bigInt 原始值

to_unix_timestamp

timestamp

timestamp 参数转换为 bigInt 原始值

to_unix_timestamp

date

date 参数转换为 bigInt 原始值

Blob 转换函数

提供了一些函数,用于将原生类型转换为二进制数据或 blob。对于 CQL 支持的每种 类型,函数 type_as_blob 接受类型为 type 的参数,并将其作为 blob 返回。相反,函数 blob_as_type 接受一个 64 位 blob 参数,并将其转换为 bigint 值。例如,bigint_as_blob(3) 返回 0x0000000000000003,而 blob_as_bigint(0x0000000000000003) 返回 3

数学函数

Cql 提供以下数学函数:absexploglog10round。这些函数的返回类型始终与输入类型相同。

函数名称 描述

abs

返回输入的绝对值。

exp

返回 e 的输入次方。

log

返回输入的自然对数。

log10

返回输入以 10 为底的对数。

round

使用舍入模式 HALF_UP 将输入舍入到最接近的整数。

集合函数

提供了一些函数,用于对集合列进行操作。

函数名称 输入类型 描述

map_keys

map

获取 map 参数的键,以 set 的形式返回。

map_values

map

获取 map 参数的值,以 list 的形式返回。

collection_count

mapsetlist

获取集合参数中的元素数量。

collection_min

setlist

获取集合参数中的最小元素。

collection_max

setlist

获取集合参数中的最大元素。

collection_sum

数值 setlist

计算集合参数中所有元素的总和。返回值与输入集合元素的类型相同,因此如果值的总和超过类型所能表示的最大值,则存在数据类型溢出的风险。

collection_avg

数值 setlist

计算集合参数中所有元素的平均值。空集合的平均值为零。返回值与输入集合元素的类型相同,可能包含舍入和截断。例如,collection_avg([1, 2]) 返回 1 而不是 1.5

数据屏蔽函数

一些函数允许隐藏包含敏感数据的列的真实内容。

函数 描述

mask_null(value)

将第一个参数替换为 null 列。返回值始终是非存在列,而不是表示 null 值的非空列。

示例

mask_null('Alice')null

mask_null(123)null

mask_default(value)

将它的参数替换为相同类型的任意固定默认值。对于文本值,这将是 ****,对于数值,为零,对于布尔值,为 false,等等。

可变长度多值类型(如列表、集合和映射)被屏蔽为空集合。

固定长度多值类型(如元组、用户定义类型 (UDT) 和向量)通过将每个值替换为值类型的默认屏蔽值来屏蔽。

示例

mask_default('Alice')'****'

mask_default(123)0

mask_default((list<int>) [1, 2, 3])[]

mask_default((vector<int, 3>) [1, 2, 3])[0, 0, 0]

mask_replace(value, replacement])

将第一个参数替换为第二个参数上的替换值。替换值需要与被替换值具有相同的类型。

示例

mask_replace('Alice', 'REDACTED')'REDACTED'

mask_replace(123, -1)-1

mask_inner(value, begin, end, [padding])

返回第一个 textvarcharascii 参数的副本,将除第一个和最后一个字符之外的每个字符替换为填充字符。第二个和第三个参数是公开的前缀和后缀的大小。可选的第四个参数是填充字符,默认情况下为 \*

示例

mask_inner('Alice', 1, 2)'Ace'

mask_inner('Alice', 1, null)'A'

mask_inner('Alice', null, 2)'*ce'

mask_inner('Alice', 2, 1, '#')'Al##e'

mask_outer(value, begin, end, [padding])

返回第一个 textvarcharascii 参数的副本,将第一个和最后一个字符替换为填充字符。第二个和第三个参数是公开的前缀和后缀的大小。可选的第四个参数是填充字符,默认情况下为 \*

示例

mask_outer('Alice', 1, 2)'*li'

mask_outer('Alice', 1, null)'*lice'

mask_outer('Alice', null, 2)'Ali'

mask_outer('Alice', 2, 1, '#')'##ic#'

mask_hash(value, [algorithm])

返回包含第一个参数哈希值的 blob。可选的第二个参数是根据可用的 Java 安全提供程序使用的哈希算法。默认哈希算法为 SHA-256

示例

mask_hash('Alice')

mask_hash('Alice', 'SHA-512')

向量相似度函数

一些函数允许获取浮点数向量的相似度得分。

函数 描述

similarity_cosine(vector, vector)

计算两个相同维度的浮点数向量的余弦相似度得分。

示例

similarity_cosine([0.1, 0.2], null)null

similarity_cosine([0.1, 0.2], [0.1, 0.2])1

similarity_cosine([0.1, 0.2], [-0.1, -0.2])0

similarity_cosine([0.1, 0.2], [0.9, 0.8])0.964238

similarity_euclidean(vector, vector)

计算两个相同维度的浮点数向量的欧几里得距离。

示例

similarity_euclidean([0.1, 0.2], null)null

similarity_euclidean([0.1, 0.2], [0.1, 0.2])1

similarity_euclidean([0.1, 0.2], [-0.1, -0.2])0.833333

similarity_euclidean([0.1, 0.2], [0.9, 0.8])0.5

similarity_dot_product(vector, vector)

计算两个相同维度的浮点数向量的点积。

示例

similarity_dot_product([0.1, 0.2], null)null

similarity_dot_product([0.1, 0.2], [0.1, 0.2])0.525

similarity_dot_product([0.1, 0.2], [-0.1, -0.2])0.475

similarity_dot_product([0.1, 0.2], [0.9, 0.8])0.625

用户定义的标量函数

用户定义函数 (UDF) 在 Cassandra 中执行用户提供的代码。默认情况下,Cassandra 支持在 Java 中定义函数。

UDF 是 Cassandra 架构的一部分,并自动传播到集群中的所有节点。UDF 可以 重载,因此具有不同参数类型的多个 UDF 可以具有相同的函数名。

JavaScript 用户定义函数在 Cassandra 4.1 中已被弃用。为了准备 Cassandra 5.0,它们的移除工作已经开始。有关更多信息,请参阅 CASSANDRA-17281、CASSANDRA-18252。

例如

CREATE FUNCTION sample ( arg int ) ...;
CREATE FUNCTION sample ( arg text ) ...;

UDF 容易受到所选编程语言的所有常见问题的困扰。因此,实现应该对空指针异常、非法参数或任何其他潜在的异常来源是安全的。函数执行期间的异常将导致整个语句失败。UDF 使用的有效查询是 SELECTINSERTUPDATE 语句。

复杂 类型(如集合、元组类型和用户定义类型)是 UDF 中有效的参数和返回值类型。元组类型和用户定义类型使用 DataStax Java 驱动程序转换函数。有关处理元组类型和用户定义类型的详细信息,请参阅 Java 驱动程序文档。

函数的参数可以是字面量或项。准备好的语句占位符也可以使用。

请注意使用双美元符号语法来包含 UDF 源代码。

例如

CREATE FUNCTION some_function ( arg int )
    RETURNS NULL ON NULL INPUT
    RETURNS int
    LANGUAGE java
    AS $$ return arg; $$;

SELECT some_function(column) FROM atable ...;
UPDATE atable SET col = some_function(?) ...;

CREATE TYPE custom_type (txt text, i int);
CREATE FUNCTION fct_using_udt ( udtarg frozen )
    RETURNS NULL ON NULL INPUT
    RETURNS text
    LANGUAGE java
    AS $$ return udtarg.getString("txt"); $$;

隐式可用的 udfContext 字段(或脚本 UDF 的绑定)提供了创建新的 UDT 和元组值所需的必要功能

CREATE TYPE custom_type (txt text, i int);
CREATE FUNCTION fct\_using\_udt ( somearg int )
    RETURNS NULL ON NULL INPUT
    RETURNS custom_type
    LANGUAGE java
    AS $$
        UDTValue udt = udfContext.newReturnUDTValue();
        udt.setString("txt", "some string");
        udt.setInt("i", 42);
        return udt;
    $$;

UDFContext 接口的定义可以在 Apache Cassandra 源代码中找到,用于 org.apache.cassandra.cql3.functions.UDFContext

public interface UDFContext
{
    UDTValue newArgUDTValue(String argName);
    UDTValue newArgUDTValue(int argNum);
    UDTValue newReturnUDTValue();
    UDTValue newUDTValue(String udtName);
    TupleValue newArgTupleValue(String argName);
    TupleValue newArgTupleValue(int argNum);
    TupleValue newReturnTupleValue();
    TupleValue newTupleValue(String cqlDefinition);
}

Java UDF 已经包含一些用于定义常见接口和类的导入。这些导入是

import java.nio.ByteBuffer;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.cassandra.cql3.functions.UDFContext;
import com.datastax.driver.core.TypeCodec;
import com.datastax.driver.core.TupleValue;
import com.datastax.driver.core.UDTValue;

请注意,这些便捷导入不适用于脚本 UDF。

CREATE FUNCTION 语句

创建新的用户定义函数使用 CREATE FUNCTION 语句

create_function_statement::= CREATE [ OR REPLACE ] FUNCTION [ IF NOT EXISTS]
	function_name '(' arguments_declaration ')'
	[ CALLED | RETURNS NULL ] ON NULL INPUT
	RETURNS cql_type
	LANGUAGE identifier
	AS string arguments_declaration: identifier cql_type ( ',' identifier cql_type )*

例如

CREATE OR REPLACE FUNCTION somefunction(somearg int, anotherarg text, complexarg frozen<someUDT>, listarg list)
    RETURNS NULL ON NULL INPUT
    RETURNS text
    LANGUAGE java
    AS $$
        // some Java code
    $$;

CREATE FUNCTION IF NOT EXISTS akeyspace.fname(someArg int)
    CALLED ON NULL INPUT
    RETURNS text
    LANGUAGE java
    AS $$
        // some Java code
    $$;

带有可选 OR REPLACE 关键字的 CREATE FUNCTION 创建一个函数或用具有相同签名的函数替换现有函数。没有 OR REPLACECREATE FUNCTION 如果已经存在具有相同签名的函数,则会失败。如果使用可选的 IF NOT EXISTS 关键字,则只有在不存在具有相同签名的其他函数时才会创建函数。OR REPLACEIF NOT EXISTS 不能一起使用。

必须为每个函数定义 null 输入值的处理方式

  • RETURNS NULL ON NULL INPUT 声明如果任何输入参数为 null,则函数将始终返回 null

  • CALLED ON NULL INPUT 声明函数将始终被执行。

函数签名

签名用于区分各个函数。签名由 <keyspace>.<function_name> 的完全限定函数名和所有参数类型的串联列表组成。

请注意,键空间名称、函数名称和参数类型受默认命名约定和大小写敏感规则的约束。

函数属于键空间;如果没有指定键空间,则使用当前键空间。用户定义函数不允许在系统键空间中使用。

DROP FUNCTION 语句

删除函数使用 DROP FUNCTION 语句

drop_function_statement::= DROP FUNCTION [ IF EXISTS ] function_name [ '(' arguments_signature ')' ]
arguments_signature::= cql_type ( ',' cql_type )*

例如

DROP FUNCTION myfunction;
DROP FUNCTION mykeyspace.afunction;
DROP FUNCTION afunction ( int );
DROP FUNCTION afunction ( text );

如果存在多个具有相同名称但不同签名的重载函数,则必须在删除命令中指定函数的参数类型,即 arguments_signature。带有可选 IF EXISTS 关键字的 DROP FUNCTION 如果函数存在则删除函数,但如果不存在则不会抛出错误。

聚合函数

聚合函数作用于一组行。每个行的值作为输入,以返回为聚合的行集返回的单个值。

如果 normal 列、scalar functionsUDT 字段、writetimettl 与聚合函数一起被选中,则为它们返回的值将是与查询匹配的第一行的值。

原生聚合

Count

count 函数可用于计算查询返回的行数。

例如

SELECT COUNT (*) FROM plays;
SELECT COUNT (1) FROM plays;

它还可以计算给定列的非空值数量

SELECT COUNT (scores) FROM plays;

Max 和 Min

maxmin 函数计算查询为给定列返回的最大值和最小值。

例如

SELECT MIN (players), MAX (players) FROM plays WHERE game = 'quake';

Sum

sum 函数将查询为给定列返回的所有值加起来。

返回值与输入集合元素的类型相同,因此如果值的总和超过类型所能表示的最大值,则存在溢出的风险。

例如

SELECT SUM (players) FROM plays;

返回值与输入值的类型相同,因此如果值的总和超过类型所能表示的最大值,则存在类型溢出的风险。您可以使用类型转换将输入值转换为足够大的类型以包含该类型。例如

SELECT SUM (CAST (players AS VARINT)) FROM plays;

Avg

avg 函数计算查询为给定列返回的所有值的平均值。

例如

SELECT AVG (players) FROM plays;

空集合的平均值为零。

返回值与输入值的类型相同,可能包含舍入和截断。例如,collection_avg([1, 2]) 返回 1 而不是 1.5。您可以使用类型转换转换为具有所需小数精度的类型。例如

SELECT AVG (CAST (players AS FLOAT)) FROM plays;

用户定义的聚合函数 (UDA)

用户定义的聚合允许创建自定义聚合函数。用户定义的聚合可以在 SELECT 语句中使用。

每个聚合函数需要一个类型为 STYPE初始状态,由 INITCOND 值定义(默认值为 null)。状态函数的第一个参数必须为 STYPE 类型。状态函数的其余参数必须与用户定义的聚合函数参数的类型匹配。状态函数对每行调用一次,状态函数返回的值将成为新的状态。处理完所有行后,可选的 FINALFUNC 将使用最后一个状态值作为其参数执行。

STYPE 值是强制性的,以便区分状态和/或最终函数的可能重载版本,因为重载可能在创建聚合函数后出现。

用户定义聚合函数的完整工作示例(假设已使用 USE 语句选择了一个键空间)

CREATE OR REPLACE FUNCTION test.averageState(state tuple<int,bigint>, val int)
    CALLED ON NULL INPUT
    RETURNS tuple
    LANGUAGE java
    AS $$
        if (val != null) {
            state.setInt(0, state.getInt(0)+1);
            state.setLong(1, state.getLong(1)+val.intValue());
        }
        return state;
    $$;

CREATE OR REPLACE FUNCTION test.averageFinal (state tuple<int,bigint>)
    CALLED ON NULL INPUT
    RETURNS double
    LANGUAGE java
    AS $$
        double r = 0;
        if (state.getInt(0) == 0) return null;
        r = state.getLong(1);
        r /= state.getInt(0);
        return Double.valueOf(r);
    $$;

CREATE OR REPLACE AGGREGATE test.average(int)
    SFUNC averageState
    STYPE tuple
    FINALFUNC averageFinal
    INITCOND (0, 0);

CREATE TABLE test.atable (
    pk int PRIMARY KEY,
    val int
);

INSERT INTO test.atable (pk, val) VALUES (1,1);
INSERT INTO test.atable (pk, val) VALUES (2,2);
INSERT INTO test.atable (pk, val) VALUES (3,3);
INSERT INTO test.atable (pk, val) VALUES (4,4);

SELECT test.average(val) FROM atable;

CREATE AGGREGATE 语句

创建(或替换)用户定义的聚合函数使用 CREATE AGGREGATE 语句

create_aggregate_statement ::= CREATE [ OR REPLACE ] AGGREGATE [ IF NOT EXISTS ]
                                function_name '(' arguments_signature')'
                                SFUNC function_name
                                STYPE cql_type:
                                [ FINALFUNC function_name]
                                [ INITCOND term ]

有关完整示例,请参见上文。

CREATE AGGREGATE 命令使用可选的 OR REPLACE 关键字创建聚合函数,或者用具有相同签名的聚合函数替换现有聚合函数。如果已存在具有相同签名的聚合函数,则不带 OR REPLACECREATE AGGREGATE 命令将失败。CREATE AGGREGATE 命令使用可选的 IF NOT EXISTS 关键字创建聚合函数(如果不存在)。OR REPLACEIF NOT EXISTS 短语不能一起使用。

STYPE 值定义状态值的类型,必须指定。可选的 INITCOND 定义聚合函数的初始状态值;默认值为 null。对于声明为 RETURNS NULL ON NULL INPUT 的状态函数,必须指定非空 INITCOND

SFUNC 值引用一个现有的函数,用作修改状态的函数。状态函数的第一个参数必须为 STYPE 类型。状态函数的其余参数必须与用户定义的聚合函数参数的类型匹配。状态函数对每行调用一次,状态函数返回的值将成为新的状态。对于声明为 RETURNS NULL ON NULL INPUT 并使用 null 调用的状态函数,状态不会更新。处理完所有行后,可选的 FINALFUNC 将使用最后一个状态值作为其参数执行。它必须只接受一个类型为 STYPE 的参数,但 FINALFUNC 的返回类型可能不同。声明为 RETURNS NULL ON NULL INPUT 的最终函数意味着如果最后一个状态为 null,则聚合函数的返回值将为 null

如果未定义 FINALFUNC,则聚合函数的总体返回类型为 STYPE。如果定义了 FINALFUNC,则为该函数的返回类型。

DROP AGGREGATE 语句

删除用户定义的聚合函数使用 DROP AGGREGATE 语句

drop_aggregate_statement::= DROP AGGREGATE [ IF EXISTS ] function_name[ '(' arguments_signature ')'
]

例如

DROP AGGREGATE myAggregate;
DROP AGGREGATE myKeyspace.anAggregate;
DROP AGGREGATE someAggregate ( int );
DROP AGGREGATE someAggregate ( text );

DROP AGGREGATE 语句删除使用 CREATE AGGREGATE 创建的聚合函数。如果存在多个具有相同名称但签名不同的重载聚合函数,则必须指定要删除的聚合函数的参数类型。

DROP AGGREGATE 命令使用可选的 IF EXISTS 关键字删除聚合函数(如果存在),如果不存在具有该签名的函数,则不执行任何操作。