除了完整的 token 匹配之外,Spanner 搜索索引还支持子字符串搜索。本页介绍了如何在 Spanner 中执行子字符串搜索,作为全文搜索的一部分。
子字符串搜索具有以下特征:
- 不区分大小写,丢弃大多数标点符号,并对空格进行标准化。
- 不进行中文、日文、韩文 (CJK) 分词,因为部分 CJK 查询经常分词错误。
- 对于多个搜索字词,结果必须包含每个字词中的子字符串。例如,'happ momen'与"happy moment"匹配,因为这两个子字符串都在文本中找到。它与"happy day"不匹配。
示例
| 存储的文本 | 子字符串查询 | 匹配 | 
|---|---|---|
| Bridge over Troubled Water | ridg roub | 是 | 
| Bridge over Troubled Water | ridg , roub | 是 | 
| Bridge over Troubled Water | over brid | 是 | 
| Bridge over Troubled Water | ate bridge | 是 | 
| Bridge over Troubled Water | Bridge bridge bridge | 是 | 
| Bridge over Troubled Water | bri trou ter | 是 | 
| Bridge over Troubled Water | bri dge | 是 | 
| Bridge over Troubled Water | troubledwater | 否 | 
| Bridge over Troubled Water | trubled | 否 | 
对于子字符串搜索,请在 TOKENLIST 列定义中使用 TOKENIZE_SUBSTRING 函数,如以下 DDL 示例所示:
GoogleSQL
CREATE TABLE Albums (
AlbumId STRING(MAX) NOT NULL,
AlbumTitle STRING(MAX),
AlbumTitle_Tokens TOKENLIST AS (TOKENIZE_SUBSTRING(AlbumTitle)) HIDDEN
) PRIMARY KEY(AlbumId);
PostgreSQL
此示例使用 spanner.tokenize_substring。
CREATE TABLE albums (
albumid character varying NOT NULL,
albumtitle character varying,
albumtitle_tokens spanner.tokenlist
    GENERATED ALWAYS AS (spanner.tokenize_substring(albumtitle)) VIRTUAL HIDDEN,
PRIMARY KEY(albumid));
在 SQL 查询中,请在 WHERE 子句中使用 SEARCH_SUBSTRING 函数。例如,以下查询会匹配上一个示例中创建的表中的标题为“happy”的专辑:
GoogleSQL
SELECT Album
FROM Albums
WHERE SEARCH_SUBSTRING(AlbumTitle_Tokens, 'happ');
PostgreSQL
此示例使用 spanner.search_substring。
SELECT album
FROM albums
WHERE spanner.search_substring(albumtitle_tokens, 'happ');
TOKENIZE_SUBSTRING 会为每个 token 生成 N 元语法,并将这些 N 元语法存储在搜索索引中。要生成的 N 元语法的最小和最大长度通过可选参数进行配置。
子字符串搜索索引所需的存储空间是相同数据的全文本索引的 10-30 倍,因为词元化会生成更多 token。特别是当 ngram_size_min 和 ngram_size_max 之间的差异增大时,这种情况尤其明显。子字符串查询也会使用更多资源来执行。
与 TOKENIZE_FULLTEXT 一样,您可以将 TOKENIZE_SUBSTRING 配置为使用特定类型的内容。
启用相对子字符串搜索
除了基本子字符串搜索之外,SEARCH_SUBSTRING 还支持相对搜索模式。相对搜索可对子字符串搜索结果进行优化。
如需启用相对搜索模式,请将 TOKENIZE_SUBSTRING 的 relative_search_types 参数设置为包含受支持相对搜索类型的元素的非空数组。
在词元化中启用相对搜索后,SEARCH_SUBSTRING 可以使用以下相对搜索类型执行查询:
- phrase:匹配连续子字符串- 示例 - 存储的文本 - 子字符串查询。 - 匹配 - Bridge over Troubled Water - bridge over - 是 - Bridge over Troubled Water - Bridge bridge bridge - 否 - Bridge over Troubled Water - brid over - 否 - Bridge over Troubled Water - ridge over trouble - 是 - Bridge over Troubled Water - bridge ove troubled - 否 - Bridge over Troubled Water - idge ove - 是 - Bridge over Troubled Water - idge , ove - 是 - Bridge over Troubled Water - RIDGE OVE - 是 - Bridge over Troubled Water - bridge water - 否 
- value_prefix:匹配连续子字符串,并且匹配必须从值的开头开始。从概念上讲,这类似于针对大小写和空格规范化的字符串的- STARTS_WITH函数。- 示例 - 存储的文本 - 子字符串查询 - 匹配 - Bridge over Troubled Water - bridge over - 是 - Bridge over Troubled Water - bridge , over - 是 - Bridge over Troubled Water - ridge over - 否 - Bridge over Troubled Water - troubled water - 否 
- value_suffix:匹配连续子字符串,并且匹配必须在值的末尾。从概念上讲,这类似于针对大小写和空格规范化的字符串的- ENDS_WITH函数。- 示例 - 存储的文本 - 子字符串查询。 - 匹配 - Bridge over Troubled Water - troubled water - 是 - Bridge over Troubled Water - troubled ; water - 是 - Bridge over Troubled Water - roubled water - 是 - Bridge over Troubled Water - troubled wate - 否 - Bridge over Troubled Water - trouble water - 否 - Bridge over Troubled Water - bridge over - 否 
- word_prefix:类似于- value_prefix,但字符串必须在字词边界(而不是值边界)处匹配。- 示例 - 存储的文本 - 子字符串查询 - 匹配 - Bridge over Troubled Water - over trouble - 是 - Bridge over Troubled Water - Over , trouble - 是 - Bridge over Troubled Water - troub water - 否 - Bridge over Troubled Water - over water - 否 - Bridge over Troubled Water - ove troubled - 否 - Bridge over Troubled Water - ver troubled - 是 
- word_suffix:与- value_suffix类似,但字符串必须在字词边界末尾进行匹配。- 示例 - 存储的文本 - 子字符串查询 - 匹配 - Bridge over Troubled Water - ver troubled - 是 - Bridge over Troubled Water - over trouble - 否 - Bridge over Troubled Water - over water - 否 - Bridge over Troubled Water - ove troubled - 否 
后续步骤
- 了解全文搜索查询。
- 了解如何对搜索结果进行排名。
- 了解如何对搜索结果进行分页。
- 了解如何混合使用全文查询和非文本查询。
- 了解如何搜索多个列。