执行子字符串搜索

除了完整的 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);

CREATE SEARCH INDEX AlbumsTitleIndex ON Albums(AlbumTitle_Tokens);

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

CREATE SEARCH INDEX albumstitleindex ON albums(albumtitle_tokens);

在 SQL 查询中,请在 WHERE 子句中使用 SEARCH_SUBSTRING 函数。例如,以下查询会匹配上一个示例中创建的表中的标题为“happy”的专辑:

GoogleSQL

SELECT AlbumId
FROM Albums
WHERE SEARCH_SUBSTRING(AlbumTitle_Tokens, 'happ');

PostgreSQL

此示例使用 spanner.search_substring。

SELECT albumid
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 否

后续步骤