多元索引操作

更新時間:
Copy as MD

在多元索引映射表上,可以在 SQL 的 WHERE 子句中使用多元索引特有的查詢函數,實現全文檢索索引、數組查詢、巢狀型別查詢、向量檢索和 JSON 資料查詢。

支援的操作

說明

使用多元索引 SQL 查詢前,需要先為多元索引建立映射關係,詳見DDL 操作

函數

查詢類型

用途

TEXT_MATCH

全文檢索索引

匹配包含至少一個查詢分詞的行。

TEXT_MATCH_PHRASE

全文檢索索引

匹配分詞按順序連續出現的行。

ARRAY_EXTRACT

數群組類型查詢

展開數組列,配合運算子過濾。

NESTED_QUERY

巢狀型別查詢

同一 JSON 元素須同時滿足所有條件。

VECTOR_QUERY_FLOAT32

向量檢索

近似最近鄰查詢。

SCORE()

向量檢索

返迴向量檢索的相關性分數。

->>

JSON 函數

提取路徑值並轉為字串。

JSON_UNQUOTE

JSON 函數

去除 JSON 值外層引號。

JSON_EXTRACT

JSON 函數

提取指定路徑的子文檔。

全文檢索索引

全文檢索索引匹配 Text 類型欄位中包含指定字串的資料,支援匹配查詢(TEXT_MATCH)和短語匹配查詢(TEXT_MATCH_PHRASE)兩種方式。

說明

使用全文檢索索引前,需要在多元索引中將目標列配置為 Text 類型並設定分詞。對於模糊分詞的列,建議使用 TEXT_MATCH_PHRASE 實現高效能的模糊查詢。

TEXT_MATCH(匹配查詢)

對查詢關鍵詞分詞,匹配至少包含一個分詞的行。返回 Boolean 類型,true 表示匹配,false 表示不匹配。

TEXT_MATCH(fieldName, text [, options])

參數

類型

說明

fieldName

STRING

要匹配的列名,該列在多元索引中必須為 Text 類型。

text

STRING

查詢關鍵詞。經分詞器分詞後進行匹配,行資料包含任意一個分詞即滿足條件。分詞類型由建立多元索引時設定的分詞器決定,未設定時預設為單字分詞。

options

STRING

可選的匹配參數,包含 operator(邏輯關係符,取值 OR 或 AND,預設 OR)和 minimum_should_match(最小匹配分詞數,預設 1)。operator 為 OR 時,列值至少包含 minimum_should_match 個分詞即滿足條件;為 AND 時,所有分詞都必須在列值中。

TEXT_MATCH_PHRASE(短語匹配查詢)

與 TEXT_MATCH 類似,但要求分詞後的多個詞在行資料中按相同順序連續出現。傳回值同為 Boolean 類型。

TEXT_MATCH_PHRASE(fieldName, text)

參數與 TEXT_MATCH 一致。區別在於 TEXT_MATCH_PHRASE 要求分詞按順序連續匹配。例如查詢值 "this is" 可以匹配 "this is tablestore",但不能匹配 "this table is" 或 "is this"。

樣本

查詢 content 列中包含 "tablestore" 分詞的資料:

SELECT * FROM search_exampletable WHERE TEXT_MATCH(content, 'tablestore') LIMIT 10;

查詢 content 列中按順序連續包含 "sql query" 的資料:

SELECT * FROM search_exampletable WHERE TEXT_MATCH_PHRASE(content, 'sql query') LIMIT 10;

使用 options 參數,匹配至少包含 2 個分詞的資料:

SELECT * FROM search_exampletable WHERE TEXT_MATCH(content, 'tablestore is cool', 'or', '2') LIMIT 10;

使用 AND 邏輯,要求所有分詞都在列值中:

SELECT * FROM search_exampletable WHERE TEXT_MATCH(content, 'tablestore is cool', 'and') LIMIT 10;

數群組類型查詢

使用 ARRAY_EXTRACT 函數查詢數群組類型列的資料。數組列在多元索引中須配置為數群組類型。可以在控制台開啟對應列的數組選項開關,或使用 SDK 將對應列的 IsArray 設定為 true。寫入資料時,數組值必須為 JSON 數組格式,例如 ["a","b","c"]

資料類型映射

資料表中資料類型

多元索引中資料類型

SQL 資料類型

字串

數組元素的實際類型(Long、Double、Boolean、Keyword、Text),同時開啟該列的數組屬性

VARCHAR(主鍵)或 MEDIUMTEXT(預定義列)

ARRAY_EXTRACT(col_name)

ARRAY_EXTRACT 將數組列展開後與運算子組合使用,作為 WHERE 子句的查詢條件。支援等值(=)、範圍(>、<)、LIKE 等運算子。

重要

不能直接將數組列與運算子組合作為查詢條件,必須通過 ARRAY_EXTRACT 函數。

使用限制

  • ARRAY_EXTRACT 只能在多元索引映射表上使用,且每次只能設定一個數組列參數。該函數只能作為 WHERE 子句的查詢條件,不能作為 SELECT 列運算式,不能用於彙總和排序。

  • 數組列本身(不使用 ARRAY_EXTRACT)可以作為 SELECT 的列名或列運算式,但不能用於彙總和排序。

  • ARRAY_EXTRACT 函數與運算子組合作為查詢條件時,不支援資料類型轉換後的計算。查詢值須與數組列的資料類型一致。例如長整型數組列支援 ARRAY_EXTRACT(col) = 1,不支援 ARRAY_EXTRACT(col) = '1'

  • Text 類型數組元素需結合 TEXT_MATCH 或 TEXT_MATCH_PHRASE 函數使用,例如 TEXT_MATCH(ARRAY_EXTRACT(col_text), 'keyword')

樣本

-- 查詢數組中包含值 'apple' 的行
SELECT * FROM search_exampletable WHERE ARRAY_EXTRACT(col_array) = 'apple';

-- 查詢數組中包含以 'd' 開頭的元素的行
SELECT * FROM search_exampletable WHERE ARRAY_EXTRACT(col_array) LIKE 'd%';

巢狀型別查詢

巢狀型別列儲存 JSON 數組,每個元素包含多個子列。資料表中該列的資料類型必須為字串,建立多元索引時將其設定為巢狀型別並配置子列的資料類型。

建立映射關係時,推薦將巢狀型別列定義為 MEDIUMTEXT 類型。內部子列會自動建立,可通過 DESCRIBE 查看,如 col_nested.namecol_nested.age。查詢時,子列名格式為 嵌套列名.子列名,多層嵌套用半形句號(.)串連,例如 col1.col2.col3

資料類型映射

資料表中資料類型

多元索引中資料類型

SQL 資料類型

字串

巢狀型別,子列資料類型與實際寫入的資料類型一致

VARCHAR(主鍵)或 MEDIUMTEXT(預定義列)

兩種查詢方式

子列直接查詢

嵌套子列直接與運算子組合使用。只要行中任意一個 JSON 元素的子列滿足條件即匹配。

SELECT * FROM search_exampletable WHERE `col_nested.age` > 30;

NESTED_QUERY 函數

要求同一個 JSON 元素同時滿足所有條件。

NESTED_QUERY(subcol_column_condition)

其中 subcol_column_condition 為同一嵌套層級下的子列查詢條件,多個條件用 AND 或 OR 串連。

兩種方式的區別

假設嵌套列 tags 有一行資料 [{"tagName":"tag1", "score":0.8}, {"tagName":"tag2", "score":0.2}]

  • tags.tagName — 匹配成功,因為第一個元素滿足 tagName 條件,第二個元素滿足 score 條件。

  • NESTED_QUERY( — 不匹配,因為沒有單個元素同時滿足兩個條件。

使用限制

  • NESTED_QUERY 只能在多元索引映射表上使用,只能作為 WHERE 子句,不能作為 SELECT 列運算式,不能用於彙總、分組和排序。

  • 嵌套子列不能作為 SELECT 列運算式,不能用於彙總、分組和排序。

  • ALTER TABLE 不能直接添加或刪除嵌套子列,只能操作整個嵌套列,子列隨嵌套列自動添加或刪除。

  • 嵌套子列不支援資料類型轉換後的計算,也不支援無法下推到多元索引的Function Compute。確保嵌套子列對應的資料類型正確。

樣本

-- 子列直接查詢:查詢嵌套列中 age > 30 的行
SELECT * FROM search_exampletable WHERE `col_nested.age` > 30;

-- NESTED_QUERY:查詢同一元素同時滿足 name 以 'I' 開頭且 age < 20 的行
SELECT * FROM search_exampletable WHERE NESTED_QUERY(`col_nested.name` LIKE 'I%' AND `col_nested.age` < 20);

-- 多層嵌套
SELECT * FROM search_exampletable WHERE NESTED_QUERY(`col1.col2` = 1 AND NESTED_QUERY(`col1.col3.col4` = 2));

虛擬列查詢

多元索引虛擬列無需修改資料表格儲存體結構,通過修改多元索引 Schema 即可實現新欄位新類型的查詢。虛擬列在映射表中按實際 SQL 資料類型定義。

資料類型映射

多元索引虛擬列類型

SQL 類型

說明

Keyword

MEDIUMTEXT

虛擬列在資料表中無對應列,僅其原始列有對應列。

Text

MEDIUMTEXT

Long

BIGINT

Double

DOUBLE

支援的用法

  • 用於 WHERE 子句的條件過濾。條件中虛擬列的資料類型與查詢參數類型必須一致。

  • 用於彙總和分組,但虛擬列在多元索引中的未經處理資料類型必須滿足對應要求。例如多元索引支援求和的類型為 Long 和 Double,Keyword 類型的虛擬列不能求和;Text 類型不支援分組。

  • 支援 TopN 查詢和排序,但排序必須配合 LIMIT 使用,不支援無 LIMIT 的排序。

使用限制

  • 虛擬列僅支援在多元索引映射表中使用。

  • 虛擬列僅支援用在查詢條件中,不能用於 SELECT 返回列值。如需傳回值,請指定虛擬列的原始列。SELECT * 不受影響,返回結果自動忽略虛擬列。

  • 虛擬列不能進行列間比較、運算和 Join。

  • 虛擬列不支援資料類型轉換後的計算,也不支援無法下推到多元索引的Function Compute。目前 SQL 查詢僅支援下推彙總函式。

樣本

建立包含虛擬列的多元索引映射表:

CREATE TABLE search_exampletable(
    col_keyword MEDIUMTEXT,
    col_keyword_virtual_long BIGINT
)
ENGINE='searchindex',
ENGINE_ATTRIBUTE='{"index_name":"exampletable_index","table_name":"exampletable"}';

使用虛擬列查詢:

SELECT * FROM search_exampletable WHERE col_keyword_virtual_long > 100 LIMIT 10;

向量檢索

使用 VECTOR_QUERY_FLOAT32 函數進行近似最近鄰查詢。向量欄位在資料表中為字串類型,在多元索引中須配置為向量類型並指定維度、資料類型和距離度量演算法。映射表中向量列的 SQL 資料類型為 MEDIUMTEXT。

VECTOR_QUERY_FLOAT32

VECTOR_QUERY_FLOAT32(fieldName, float32QueryVector, topK, filter)

參數

是否必選

說明

fieldName

向量列名,必須為多元索引中的向量類型欄位。

float32QueryVector

查詢向量,維度必須與多元索引中向量欄位的維度一致。

topK

返回最鄰近的 topK 個結果。K 值越大召回率越好,但查詢延遲和費用越高。當 topK 小於 LIMIT 值時,服務端自動將 topK 放大到 LIMIT 值。關於 topK 最大值的說明,請參見多元索引使用限制

filter

查詢過濾器,支援組合使用任意非向量檢索的查詢條件。filter 中的過濾條件在向量檢索前執行,先縮小候選集再進行向量匹配。也可以在 WHERE 子句中使用 AND 添加額外過濾條件,但此時過濾在向量檢索後從 topK 結果中篩選。

SCORE() 函數

配合 VECTOR_QUERY_FLOAT32 使用,作為 SELECT 列運算式返回查詢結果的相關性分數,分數越大表示越相似。

SCORE()

使用限制

  • VECTOR_QUERY_FLOAT32 只能在多元索引映射表上使用,必須配合 LIMIT,不支援 HAVING 子句。

  • VECTOR_QUERY_FLOAT32 只能作為 WHERE 子句,不能作為 SELECT 列運算式,不能用於彙總、分組和排序。

  • SCORE() 只能配合 VECTOR_QUERY_FLOAT32 使用,只能作為 SELECT 列運算式,不能用於 WHERE、彙總和排序。

  • WHERE 子句中的其他條件必須能下推到多元索引執行,否則查詢失敗。關於支援下推的運算元,請參見SQL查詢最佳化

樣本

查詢 col_vector 列與指定向量最相似的 10 個結果:

SELECT *, SCORE() FROM exampletable WHERE VECTOR_QUERY_FLOAT32(col_vector, '[1.5, -1.5, 2.5, -2.5]', 10) LIMIT 10;

使用 filter 先篩選再向量檢索(filter 在向量檢索前縮小候選集,結果更精確):

SELECT *, SCORE() FROM exampletable WHERE VECTOR_QUERY_FLOAT32(col_vector, '[1.5, -1.5, 2.5, -2.5]', 100, col_keyword='cat_a' AND year_num=2024) LIMIT 10;

在 WHERE 中用 AND 附加過濾(從 topK 結果中篩選,topK 結果可能不包含所有滿足條件的行):

SELECT *, SCORE() FROM exampletable WHERE col_keyword='cat_a' AND VECTOR_QUERY_FLOAT32(col_vector, '[1.5, -1.5, 2.5, -2.5]', 500) LIMIT 10;

JSON 函數

Table Store SQL 的 JSON 函數遵循 MySQL 5.7 文法,可以從 JSON 格式的列中提取資料。支援以下函數。

函數

文法

說明

->>

col->>'$.path'

提取值並轉為字串,等效於 JSON_UNQUOTE(JSON_EXTRACT())

JSON_UNQUOTE

JSON_UNQUOTE(json_val)

去除 JSON 值外層引號,返回字串

JSON_EXTRACT

JSON_EXTRACT(json_doc, path[, path] ...)

提取指定路徑的子文檔,傳回值保留 JSON 格式

->>(JSON 路徑提取)

從 JSON 列中提取指定路徑的值並取值 (Dereference)轉換為字串,等效於 JSON_UNQUOTE(JSON_EXTRACT())

column->>'$.path'

參數

類型

說明

column

STRING

列名。

path

STRING

JSON 路徑運算式,必須以 $ 開頭。詳細文法請參見下方 JSON Path 文法。

樣本

SELECT col_json->>'$.city' AS city FROM exampletable LIMIT 10;

JSON_UNQUOTE

去除 JSON 值外層引號,返回字串。如果參數為 NULL,則返回 NULL。

JSON_UNQUOTE(json_val)

參數

類型

說明

json_val

STRING

JSON 值,通常為 JSON_EXTRACT 的傳回值。如果值以雙引號開頭和結尾但不是有效 JSON 字串文字,則會報錯。

樣本

SELECT JSON_UNQUOTE(JSON_EXTRACT(col_json, '$.city')) AS city FROM exampletable LIMIT 10;

JSON_EXTRACT

從 JSON 列中提取指定路徑的子文檔,傳回值保留 JSON 格式(字串值帶引號)。支援同時提取多個 path,多個 path 的結果以數組格式返回。

重要

由於Table Store不支援原生 JSON 類型,JSON_EXTRACT 不能單獨使用(會報 invalid column type: json 錯誤),需要結合 JSON_UNQUOTE 使用。

JSON_EXTRACT(json_doc, path[, path] ...)

參數

類型

說明

json_doc

STRING

JSON 格式的文檔。如果不是有效 JSON 文檔,則會報錯。

path

STRING

JSON 路徑運算式,必須以 $ 開頭。支援傳入多個 path。如果任何參數為 NULL 或路徑在文檔中未找到值,則返回 NULL。如果 path 不是有效路徑運算式,則會報錯。

樣本

提取單個路徑:

SELECT JSON_UNQUOTE(JSON_EXTRACT(col_json, '$.city')) AS city FROM exampletable WHERE pk = 1;

同時提取多個路徑(結果以數組格式返回):

-- 假設 col_json 的值為 {"a": 1, "b": 2, "c": {"d": 4}}
SELECT JSON_UNQUOTE(JSON_EXTRACT(col_json, '$.a', '$.b', '$.c.d')) AS subdoc FROM exampletable WHERE pk = 1;
-- 返回結果:[1, 2, 4]

JSON Path 文法

path 必須以 $ 開頭,$ 表示整個 JSON 文檔。其後可添加直接選取器,選取器可組合使用。

選取器

樣本

說明

$.key

$.a、$.c.d

Object 成員訪問。key 含空格時用雙引號包裹,例如 $."a fish"

[N]

$[0]、$.f[1]

Array 元素訪問,索引從 0 開始。

.*

$.*

Object 萬用字元,返回所有成員的值。

[*]

$.arr[*]

Array 萬用字元,返回所有元素的值。

prefix**suffix

$**.d

路徑萬用字元,匹配所有以 prefix 開始、以 suffix 結尾的路徑。

JSON Object 查詢樣本

假設 JSON 列的值為 {"a": 1, "f": [1, 2, 3], "c": {"d": 4}}

路徑

傳回值

說明

$

{"a": 1, "c": {"d": 4}, "f": [1, 2, 3]}

整個文檔

$.a

1

直接成員

$.c

{"d": 4}

嵌套 Object

$.c.d

4

嵌套 Object 成員

$.f[1]

2

Array 元素

JSON Array 查詢樣本

假設 JSON 列的值為 [3, {"a": [5, 6], "b": 10}, [99, 100]]。當傳回值為非標量值時,可以繼續巢狀查詢。

路徑

傳回值

說明

$[0]

3

標量元素

$[1]

{"a": [5, 6], "b": 10}

非標量,可繼續嵌套

$[1].a

[5, 6]

嵌套 Object 成員

$[1].a[1]

6

嵌套 Array 元素

$[1].b

10

嵌套 Object 成員

$[2][0]

99

嵌套 Array 元素

$[3]

NULL

越界返回 NULL