本页介绍了如何为表添加令牌化。必须进行令牌化,才能创建在搜索索引中使用的令牌。
令牌化是将值转换为令牌的过程。您用于对文档进行分词的方法决定了用户可以对文档执行的搜索类型和效率。
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
函数从 Albums
表中的 AlbumTitles
创建令牌。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") |
一个令牌:[旅行] |