多元索引操作

更新时间:
复制 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.name、col_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 不能直接添加或删除嵌套子列,只能操作整个嵌套列,子列随嵌套列自动添加或删除。

  • 嵌套子列不支持数据类型转换后的计算,也不支持无法下推到多元索引的函数计算。确保嵌套子列对应的数据类型正确。

示例

-- 子列直接查询:查询嵌套列中 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。

  • 虚拟列不支持数据类型转换后的计算,也不支持无法下推到多元索引的函数计算。目前 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 函数

表格存储 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 列中提取指定路径的值并取消引用转换为字符串,等效于 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 的结果以数组格式返回。

重要

由于表格存储不支持原生 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