本页介绍了如何执行混合全文和非文本数据的搜索。
执行混合全文和非文本搜索
搜索索引支持全文、完全匹配、数值列和 JSON/JSONB 列。您可以将文本条件和非文本条件组合在 WHERE
子句中,类似于多列搜索查询。查询优化器会尝试使用搜索索引优化非文本谓词。如果无法做到这一点,Spanner 会针对与搜索索引匹配的每行评估条件。未存储在搜索索引中的引用列会从基表中提取。
请参考以下示例:
GoogleSQL
CREATE TABLE Albums (
AlbumId STRING(MAX) NOT NULL,
Title STRING(MAX),
Rating FLOAT64,
Genres ARRAY<STRING(MAX)>,
Likes INT64,
Cover BYTES(MAX),
Title_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(Title)) HIDDEN,
Rating_Tokens TOKENLIST AS (TOKENIZE_NUMBER(Rating)) HIDDEN,
Genres_Tokens TOKENLIST AS (TOKEN(Genres)) HIDDEN
) PRIMARY KEY(AlbumId);
CREATE SEARCH INDEX AlbumsIndex
ON Albums(Title_Tokens, Rating_Tokens, Genres_Tokens)
STORING (Likes);
PostgreSQL
Spanner PostgreSQL 支持具有以下限制:
spanner.tokenize_number
函数仅支持bigint
类型。spanner.token
不支持对数组进行词元化处理。
CREATE TABLE albums (
albumid character varying NOT NULL,
title character varying,
rating bigint,
genres character varying NOT NULL,
likes bigint,
cover bytea,
title_tokens spanner.tokenlist AS (spanner.tokenize_fulltext(title)) VIRTUAL HIDDEN,
rating_tokens spanner.tokenlist AS (spanner.tokenize_number(rating)) VIRTUAL HIDDEN,
genres_tokens spanner.tokenlist AS (spanner.token(genres)) VIRTUAL HIDDEN,
PRIMARY KEY(albumid));
CREATE SEARCH INDEX albumsindex
ON albums(title_tokens, rating_tokens, genres_tokens)
INCLUDE (likes);
对此表执行查询的行为包括:
Rating
和Genres
包含在搜索索引中。Spanner 使用搜索索引发布列表加快满足条件的速度。ARRAY_INCLUDES_ANY
、ARRAY_INCLUDES_ALL
是 GoogleSQL 函数,PostgreSQL 方言不支持。SELECT Album FROM Albums WHERE Rating > 4 AND ARRAY_INCLUDES_ANY(Genres, ['jazz'])
查询可以以任何方式组合连词、析取和取反,包括混合使用全文本和非文本谓词。此查询完全由搜索索引加速。
SELECT Album FROM Albums WHERE (SEARCH(Title_Tokens, 'car') OR Rating > 4) AND NOT ARRAY_INCLUDES_ANY(Genres, ['jazz'])
Likes
存储在索引中,但架构不会请求 Spanner 为其可能的值构建 token 索引。因此,Title
上的全文谓词和Rating
上的非文本谓词会加速,但Likes
上的谓词不会加速。在 Spanner 中,查询会提取Title
中包含“car”一词且评分超过 4 的所有文档,然后过滤掉没有至少 1000 个点赞的文档。如果几乎所有专辑的标题中都包含“car”一词,并且几乎所有专辑的评分都为 5 分,但只有少数专辑的点赞数为 1000,那么此查询会使用大量资源。在这种情况下,将Likes
与Rating
类似地编入索引可节省资源。GoogleSQL
SELECT Album FROM Albums WHERE SEARCH(Title_Tokens, 'car') AND Rating > 4 AND Likes >= 1000
PostgreSQL
SELECT album FROM albums WHERE spanner.search(title_tokens, 'car') AND rating > 4 AND likes >= 1000
Cover
不会存储在索引中。以下查询会在AlbumsIndex
和Albums
之间执行后向联接,以便为所有匹配的专辑提取Cover
。GoogleSQL
SELECT AlbumId, Cover FROM Albums WHERE SEARCH(Title_Tokens, 'car') AND Rating > 4
PostgreSQL
SELECT albumid, cover FROM albums WHERE spanner.search(title_tokens, 'car') AND rating > 4