本页介绍了如何为表添加令牌化。“令牌化”现为 是创建要在现有集群中使用的 搜索索引。
概览
词元化是将值转换为词元的过程。您采用的方法 对文档进行标记化的过程决定了 用户可以对其执行操作
Spanner 为自然语言文本、子字符串、逐字逐句文本、数字和布尔值提供了 tokenizer。数据库架构使用 标记生成器。分词器 具有以下特征:
- 每个标记生成器都是一个 SQL 函数,用于获取输入,例如字符串或 数字,以及用于其他选项的具名实参。
- 分词器会输出
TOKENLIST
。
例如,文本字符串 The quick brown fox jumps over the lazy dog
会被标记为 [the,quick,brown,fox,jumps,over,the,lazy,dog]
。HTML 字符串 The <b>apple</b> is <i>red</i>
被标记化为
[the,apple,is,red]
。
令牌具有以下特征:
- 令牌存储在使用
TOKENLIST
数据类型的列中。 - 每个令牌都存储为一系列字节,并包含一组可选的关联属性。例如,在全文应用中,令牌是 通常是文本文档中的一个单词。
- 对 HTML 值进行标记化处理时,Spanner 会生成属性, 来指示某个词元在文档中的重要程度。 Spanner 会使用这些属性进行评分,以提升更显眼的字词(例如标题)的权重。
词元化器
Spanner 支持以下分词器函数:
全文分词器 (
TOKENIZE_FULLTEXT
) 会为自然语言查询生成整词令牌。示例
以下两个函数
TOKENIZE_FULLTEXT("Yellow apple") TOKENIZE_FULLTEXT("Yellow <b>apple</b>", content_type=>"text/html")
会生成相同的词元:
[yellow,apple]
。子字符串分词器 (
TOKENIZE_SUBSTRING
) 会为每个字词的每个 n-gram 生成词法单元。用于查找文本中字词的子字符串。示例
TOKENIZE_SUBSTRING("hello world", ngram_size_min=>4, ngram_size_max=>6)
生成以下令牌:
[ello,hell,hello,orld,worl,world]
。N 元语法分词器 (
TOKENIZE_NGRAMS
) 会根据输入生成 N 元语法(而不会将其拆分为单独的字词)。它用于加快正则表达式谓词的速度。示例
以下函数:
TOKENIZE_NGRAMS("Big Time", ngram_size_min=>4, ngram_size_max=>4)
生成以下令牌:
["Big ","ig T","g Ti"," Tim", "Time"]
。完全匹配分词器 (
TOKEN
) 和TOKENIZE_BOOL
) 用于查找某一列中包含特定值的行。 例如,将商品清单编入索引的应用可能需要 搜索具有特定品牌和颜色的商品。示例
以下函数:
TOKEN("hello") TOKEN(["hello", "world"])
分别生成以下令牌:
[hello]
和[hello,world]
。以下函数:
TOKENIZE_BOOL(true)
生成以下令牌:
[y]
。分词器数量 (
TOKENIZE_NUMBER
) 用于生成一组词元,以加快数字比较的速度 搜索。对于等式条件,标记是数字本身。对于范围条件(例如rating >= 3.5
),一组令牌会更为复杂。示例
以下函数语句:
TOKENIZE_NUMBER(42, comparison_type=>"equality") TOKENIZE_NUMBER(42, comparison_type=>"all", granularity=>10, min=>1, max=>100)
分别生成以下令牌:
"==42"
和"==42"
。"[1,75]"
、"[36, 45]"
、"[36,55]"
、"[36, 75]"
。
令牌化函数通常用于生成的列表达式中。这些列被定义为 HIDDEN
,因此不会包含在 SELECT *
查询结果中。
以下示例使用全文分词器和数字分词器创建一个用于存储音乐专辑名称和评分的的数据库。DDL 语句 会做两件事:
- 定义数据列
AlbumTitle
和Rating
。 定义
AlbumTitle_Tokens
和AlbumRating_Tokens
。这些TOKENLIST
列会对数据列中的值进行分词,以便 Spanner 对其编制索引。CREATE TABLE Albums ( AlbumId STRING(MAX) NOT NULL, AlbumTitle STRING(MAX), Rating FLOAT64, AlbumTitle_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN, Rating_Tokens TOKENLIST AS (TOKENIZE_NUMBER(Rating)) HIDDEN ) PRIMARY KEY(AlbumId);
每当修改基值时,AlbumTitle_Tokens
和 Rating_Tokens
会自动更新
对纯文本或 HTML 内容进行词元化
文本标记化支持纯文本和 HTML 内容类型。使用 Spanner TOKENIZE_FULLTEXT
函数创建令牌。然后,使用 CREATE SEARCH INDEX
DDL 语句生成搜索索引。
例如,以下 CREATE TABLE
DDL 语句使用
TOKENIZE_FULLTEXT
函数,用于通过 AlbumTitles
中的
Albums
表。CREATE SEARCH INDEX
DDL 语句会使用新的 AlbumTitles_Tokens
创建搜索索引。
CREATE TABLE Albums (
AlbumId STRING(MAX) NOT NULL,
AlbumTitle STRING(MAX),
AlbumTitle_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN
) PRIMARY KEY(AlbumId);
CREATE SEARCH INDEX AlbumsIndex ON Albums(AlbumTitle_Tokens)
令牌化过程使用以下规则:
- 令牌化不包括 词干提取或更正 包含拼写错误的字词。例如,在“一只猫在看着一群猫”这样的句子中,“cat”和“cats”这两个令牌会被单独编入索引。与其他在写入期间将令牌标准化的搜索引擎相比, Spanner 提供了将搜索查询扩展到 包含不同形式的字词。如需了解详情,请参阅 增强型查询模式。
- 搜索索引中会包含停用字词(例如“a”)。
- 全文搜索始终不区分大小写。标记化过程 将所有词法单元转换为小写形式。
词条化过程会跟踪原始文本中每个词条的位置。这些位置稍后将用于匹配短语。这些位置已存储 在搜索索引中与 docid 匹配。
Google 不断改进标记化算法。在某些情况下, 会导致字符串在未来的词法单元化处理方式与之前不同 令牌化处理。我们预计此类情况非常罕见。例如, 如果中文、日语和韩语 (CJK) 语言有改进, 细分。
content_type
参数用于指定内容格式是使用纯文本还是 HTML。使用以下设置设置 content_type
:
- 如需进行文本标记化,请将
content_type
参数设置为“text/plain
”。 这是默认设置。 - 对于 HTML 令牌化,请将
content_type
参数设置为"text/html
"。如果不使用此参数,系统会将 HTML 标记视为标点符号。在 HTML 模式下 Spanner 使用启发法推断文本在 页面。例如,文本是在标题中还是字体大小。 支持的 HTML 属性包括small
、medium
、large
、title
和“link”。与位置一样,此属性会与令牌一起存储在搜索索引中。令牌化不会为任何 HTML 标记创建令牌。
令牌属性不会影响匹配,也不会影响 SEARCH
或
SEARCH_SUBSTRING
函数。它们仅用于排名。
以下示例展示了如何对文本进行标记化:
CREATE TABLE T (
...
Text STRING(MAX),
Html STRING(MAX),
Text_Tokens TOKENLIST
AS (TOKENIZE_FULLTEXT(Text, content_type=>"text/plain")) HIDDEN,
Html_Tokens TOKENLIST
AS (TOKENIZE_FULLTEXT(Html, content_type=>"text/html")) HIDDEN
) PRIMARY KEY(...);
使用 language_tag
参数优化语言检测
默认情况下,词法单元化会自动检测输入语言。当输入语言已知时,可以使用 language_tag
参数来优化此行为:
AlbumTitle_Tokens TOKENLIST
AS (TOKENIZE_FULLTEXT(AlbumTitle, language_tag=>"en-us")) HIDDEN
大多数应用会将 language_tag
参数留空,而改为依赖于自动语言检测。对中文、韩语和日语等亚洲语言进行细分时,无需设置令牌化语言。
以下示例展示了 language_tag
影响词元化的情况:
标记化函数 | 生成的令牌 |
---|---|
TOKENIZE_FULLTEXT("A tout pourquoi il y a un parce que") |
[a、tout、pourquoi、il、ya、un、parce、que] |
TOKENIZE_FULLTEXT("A tout pourquoi il y a un parce que", \ language_tag=>"fr" ) |
[a, tout, pourquoi, il, y, a, un, parce, que] |
TOKENIZE_FULLTEXT("旅 行") |
两个令牌:[旅,行] |
TOKENIZE_FULLTEXT("旅 行", language_tag=>"zh") |
一个令牌:[旅行] |