在多元索引映射表上,可以在 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 格式的列中提取数据。支持以下函数。
函数 | 语法 | 说明 |
->> |
| 提取值并转为字符串,等效于 |
JSON_UNQUOTE |
| 去除 JSON 值外层引号,返回字符串 |
JSON_EXTRACT |
| 提取指定路径的子文档,返回值保留 JSON 格式 |
->>(JSON 路径提取)
从 JSON 列中提取指定路径的值并取消引用转换为字符串,等效于 JSON_UNQUOTE(JSON_EXTRACT())。
column->>'$.path'参数 | 类型 | 说明 |
column | STRING | 列名。 |
path | STRING | JSON 路径表达式,必须以 |
示例
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 路径表达式,必须以 |
示例
提取单个路径:
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 含空格时用双引号包裹,例如 |
[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 |