Cassandra 文件

版本

您正在檢視預發行版本的說明文件。

函數

CQL 支援 2 個主要類別的函數

在這兩種情況下,CQL 都提供多個原生「硬式編碼」函數,以及建立新的使用者定義函數的能力。

預設情況下,考量到安全性問題,預設會停用使用者定義函數(即使已啟用,使用者定義函數的執行也會受到沙盒保護,而且「流氓」函數不應被允許執行惡意行為,但沒有任何沙盒是完美的,因此使用使用者定義函數是選擇加入的)。請參閱 cassandra.yaml 中的 user_defined_functions_enabled 以啟用它們。

函數會根據其名稱來識別

function_name ::= [ keyspace_name'.' ] name

純量函數

原生函數

轉換

cast 函數可將一種原生資料類型轉換為另一種。

下表說明 cast 函數支援的轉換。Cassandra 會自動忽略任何將資料類型轉換為其本身資料類型的轉換。

轉換為

ascii

textvarchar

bigint

tinyintsmallintintfloatdoubledecimalvarinttextvarchar

boolean

textvarchar

counter

tinyintsmallintintbigintfloatdoubledecimalvarinttextvarchar

date

timestamp

decimal

tinyintsmallintintbigintfloatdoublevarinttextvarchar

double

tinyintsmallintintbigintfloatdecimalvarinttextvarchar

float

tinyintsmallintintbigintdoubledecimalvarinttextvarchar

inet

textvarchar

int

tinyintsmallintbigintfloatdoubledecimalvarinttextvarchar

smallint

tinyintintbigintfloatdoubledecimalvarinttextvarchar

time

textvarchar

timestamp

datetextvarchar

timeuuid

timestampdatetextvarchar

tinyint

tinyintsmallintintbigintfloatdoubledecimalvarinttextvarchar

uuid

textvarchar

varint

tinyintsmallintintbigintfloatdoubledecimaltextvarchar

轉換嚴格依循 Java 的語意。例如,double 值 1 會轉換為文字值 '1.0'。例如

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

Token

token 函數會計算給定分區金鑰的 token。token 函數的確切簽章取決於相關的表格和叢集使用的分區器。

token 參數的類型取決於分區金鑰欄位類型。傳回的類型取決於定義的分區器

分區器 傳回的類型

Murmur3Partitioner

bigint

RandomPartitioner

varint

ByteOrderedPartitioner

blob

例如,考慮下列表格

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

表格使用預設的 Murmur3Partitioner。token 函數使用單一參數 text,因為分區金鑰是文字類型的 userid。傳回的類型將會是 bigint

Uuid

uuid 函數不接受任何參數,並會產生適合用於 INSERTUPDATE 陳述式的隨機類型 4 uuid。

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');

將選取所有 timeuuid 欄位 t 晚於 '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 產生程序。特別是,這兩個方法傳回的值不會是唯一的。因此,僅將這些方法用於 查詢,而不是 插入,以防止可能的資料覆寫。

Datetime 函數

擷取目前的日期/時間

下列函數可用於在函數被呼叫時擷取日期/時間

函數名稱 輸出類型

current_timestamp

timestamp

current_date

date

current_time

time

current_timeuuid

timeUUID

例如,可以使用下列方式擷取過去兩天的資料

SELECT * FROM myTable WHERE date >= current_date() - 2d;
時間轉換函數

提供了一些函數,用於將 timeuuidtimestampdate 轉換成另一種 原生 類型。

函數名稱 輸入類型 說明

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 值的非 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
    $$;

CREATE FUNCTION 搭配選用的 OR REPLACE 關鍵字會建立函式或取代具有相同簽章的現有函式。如果已經存在具有相同簽章的函式,則不含 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 函式UDT 欄位、writetimettl,則為其傳回的值將是符合查詢的第一列的值。

原生聚集

計數

count 函式可用於計數查詢傳回的列。

例如

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

它也可以計數特定欄位的非 Null 值

SELECT COUNT (scores) FROM plays;

最大值和最小值

maxmin 函式計算查詢針對特定欄位傳回的最大值和最小值。

例如

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

總和

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 會失敗。具有選用 IF NOT EXISTS 關鍵字的 CREATE AGGREGATE 命令會在聚合不存在時建立聚合。OR REPLACEIF NOT EXISTS 短語不能一起使用。

STYPE 值定義狀態值的類型,且必須指定。選用的 INITCOND 定義聚合的初始狀態值;預設值為 null。對於宣告為 RETURNS NULL ON NULL INPUT 的狀態函數,必須指定非 nullINITCOND

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 建立的聚合。如果有多個重載的聚合具有相同名稱但簽章不同,則您必須指定要刪除的聚合的引數類型。

包含選用 IF EXISTS 關鍵字的 DROP AGGREGATE 指令會在聚合存在時將其刪除,如果簽章中沒有函數,則不會執行任何動作。