本页介绍如何将 TOKENLIST
中的
搜索索引(当您设置架构时)
或搜索查询中。
在搜索索引中组合 TOKENLIST
有时,您需要应用在多个字段中进行搜索。在 有时,应用需要在所有字段中进行搜索。例如,在包含两个字符串列的表中,您可能希望应用搜索这两个列,而不区分匹配项来自哪个列。
在 Spanner 中,您可以通过以下两种方式实现此目的:
使用第二种方法存在两个问题:
- 如果您想单独为
Title
或Studio
编制索引,除了在组合TOKENLIST
中为它们编制索引之外,系统还会对同一文本进行两次标记化。这会导致事务使用更多资源。 - 词组搜索会涵盖这两个字段。例如,如果
@p
设置为"Blue Note"
,则会匹配同时包含Title
="Big Blue Note" 和Studio
="Blue Note Studios" 的行。
第一种方法可以解决这些问题,因为一个词组只会与一个字段匹配,并且如果同时为单个 TOKENLIST
和组合 TOKENLIST
编制索引,则每个字符串字段只会被标记化一次。即使每个字符串字段仅进行一次分词,生成的 TOKENLIST 也会单独存储在索引中。
分别标记化字词并串联 TOKENLIST
值
以下示例会对每个字词进行标记化处理,并串联 TOKENLIST
值:
CREATE TABLE Albums (
AlbumId STRING(MAX) NOT NULL,
Title STRING(MAX),
Studio STRING(MAX),
Title_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(Title)) HIDDEN,
Studio_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(Studio)) HIDDEN,
Combined_Tokens TOKENLIST AS (TOKENLIST_CONCAT([Title_Tokens, Studio_Tokens])) HIDDEN,
) PRIMARY KEY(AlbumId);
CREATE SEARCH INDEX AlbumsIndex ON Albums(Combined_Tokens);
SELECT AlbumId FROM Albums WHERE SEARCH(Combined_Tokens, @p);
TOKENLIST
串联也可以完全在查询端实现。如需了解详情,请参阅查询端 TOKENLIST
串联。
全文搜索和子字符串搜索均支持 TOKENLIST_CONCAT
。Spanner 不允许您在同一 TOKENLIST_CONCAT
调用中混用令牌化类型,例如 TOKENIZE_FULLTEXT
和 TOKENIZE_SUBSTRING
。
您可以在非存储列中更改文本 TOKENLIST
列的定义,以添加其他列。如果您想向 TOKENLIST_CONCAT
添加其他列,这会非常有用。更改生成的列表达式不会回填索引中的现有行。
串联字符串并对结果进行标记化处理
以下示例会串联字符串并对结果进行分词:
CREATE TABLE Albums (
AlbumId STRING(MAX) NOT NULL,
Title STRING(MAX),
Studio STRING(MAX),
Combined_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(Title || " " || Studio)) HIDDEN,
) PRIMARY KEY(AlbumId);
CREATE SEARCH INDEX AlbumsIndex ON Albums(Combined_Tokens);
SELECT AlbumId FROM Albums WHERE SEARCH(Combined_Tokens, @p);
查询端 TOKENLIST
串联
对串联的 TOKENLIST
编入索引的代价是增加存储和写入费用。现在,每个令牌都会在磁盘上存储两次:
一次是在原始 TOKENLIST
的发布列表中添加一次,另一次是在发布列表中添加
组合 TOKENLIST
的整个有效期。在查询端对 TOKENLIST
列进行串联可以避免此开销,但查询会使用更多计算资源。
如需串联多个 TOKENLIST
,请使用
TOKENLIST_CONCAT
函数
SEARCH
查询。在本部分中,我们将使用以下示例架构:
CREATE TABLE Albums (
AlbumId STRING(MAX) NOT NULL,
Title STRING(MAX),
Studio STRING(MAX),
Title_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(Title)) HIDDEN,
Studio_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(Studio)) HIDDEN,
) PRIMARY KEY(AlbumId);
CREATE SEARCH INDEX AlbumsIndex ON Albums(Title_Tokens, Studio_Tokens);
以下查询会搜索 Title
和 Studio
列中任意位置包含“blue”和“note”标记的行。这包括 Title
列和 Studio
列中同时包含“blue”和“note”的行,以及 Title
列中包含“blue”且 Studio
列中包含“note”的行,或相反的情况。
SELECT AlbumId
FROM Albums
WHERE SEARCH(TOKENLIST_CONCAT([AlbumTitle_Tokens, Studio_Tokens]), 'blue note')
写入端和查询端 TOKENLIST
串联产生的结果相同。
两者的选择是在磁盘费用和查询费用之间进行权衡取舍。
或者,应用可以搜索多个 TOKENLIST
列,并将 OR
与 SEARCH
函数搭配使用:
SEARCH(AlbumTitle_Tokens, 'Blue Note') OR SEARCH(Studio_Tokens, 'Blue Note')
不过,这具有不同的语义。它与以下影集不匹配:
“AlbumTitle_Tokens
”包含“blue”,但没有“note”且Studio_Tokens
“note”,而不是“blue”。