本頁說明如何在設定結構定義時,或在 Spanner 中執行全文搜尋時,將 TOKENLIST 串連至搜尋索引。
在搜尋索引中合併 TOKENLIST
有時,您需要應用程式在個別欄位中搜尋。在其他情況下,應用程式需要搜尋所有欄位。舉例來說,在含有兩個字串資料欄的表格中,您可能希望應用程式在兩個資料欄中搜尋,而不區分比對結果來自哪個資料欄。
在 Spanner 中,有兩種方法可以達成此目的:
第二種方法有兩個問題:
- 如果您想個別為
Title或Studio建立索引,除了在合併的TOKENLIST中建立索引外,系統會對相同文字進行兩次權杖化。導致交易使用更多資源。 - 詞組搜尋會同時搜尋這兩個欄位。舉例來說,如果
@p設為"Blue Note",則會比對同時包含Title="Big Blue Note" 和Studio="Blue Note Studios" 的資料列。
第一種方法可解決這些問題,因為片語只會比對一個欄位,且如果個別和合併的 TOKENLIST 都已建立索引,每個字串欄位只會進行一次權杖化。即使每個字串欄位只會經過一次權杖化,產生的 TOKENLIST 仍會分別儲存在索引中。
分別將字詞符記化,並串連 TOKENLIST
下列範例會將每個字詞權杖化,並使用 TOKENLIST_CONCAT 串連 TOKENLIST:
GoogleSQL
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);
PostgreSQL
PostgreSQL 使用
spanner.tokenlist_concat
進行串連。查詢參數 $1 會繫結至「Hatel Kaliphorn」。
CREATE TABLE albums (
albumid character varying NOT NULL,
title character varying,
studio character varying,
title_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(title)) VIRTUAL HIDDEN,
studio_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(studio)) VIRTUAL HIDDEN,
combined_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenlist_concat(ARRAY[spanner.tokenize_fulltext(title), spanner.tokenize_fulltext(studio)])) VIRTUAL HIDDEN,
PRIMARY KEY(albumid));
CREATE SEARCH INDEX albumsindex ON albums(combined_tokens);
SELECT albumid FROM albums WHERE spanner.search(combined_tokens, $1);
請注意,tokenlist_concat 不會呼叫 title_tokens 或 studio_tokens,而是呼叫 spanner.tokenize_fulltext(title) 和 spanner.tokenize_fulltext(studio)。這是因為 PostgreSQL 不支援參照其他產生的資料欄中的產生資料欄。spanner.tokenlist_concat 需要呼叫權杖化函式,而不是直接參照權杖清單資料欄。
TOKENLIST 串連也可以完全在查詢端實作。詳情請參閱「查詢端串連」。TOKENLIST
TOKENLIST_CONCAT 支援全文和子字串搜尋。Spanner 不允許您在同一個 TOKENLIST_CONCAT 呼叫中混合使用權杖化類型,例如 TOKENIZE_FULLTEXT 和 TOKENIZE_SUBSTRING。
在 GoogleSQL 中,您可以在非儲存的資料欄中變更文字 TOKENLIST 資料欄的定義,以新增其他資料欄。如要為 TOKENLIST_CONCAT 新增其他資料欄,這項功能就非常實用。變更產生的資料欄運算式不會回填索引中的現有資料列。
串連字串並將結果標記化
以下範例會串連字串,並將結果權杖化:
GoogleSQL
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);
PostgreSQL
CREATE TABLE albums (
albumid character varying NOT NULL,
title character varying,
studio character varying,
combined_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(title || ' ' || studio)) VIRTUAL HIDDEN,
PRIMARY KEY(albumid));
CREATE SEARCH INDEX albumsindex ON albums(combined_tokens);
SELECT albumid FROM albums WHERE spanner.search(combined_tokens, $1);
查詢端 TOKENLIST 串連
為串連的 TOKENLIST建立索引的缺點是會增加儲存空間和寫入費用。每個權杖現在都會儲存在磁碟上兩次:一次是在原始 TOKENLIST 的發布清單中,另一次是在合併 TOKENLIST 的發布清單中。在查詢端串連 TOKENLIST 欄可避免這項費用,但查詢會使用更多運算資源。
如要串連多個 TOKENLIST,請在 SEARCH 查詢中使用 TOKENLIST_CONCAT 函式。在本節中,我們使用下列範例結構定義:
GoogleSQL
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);
PostgreSQL
CREATE TABLE albums (
albumid character varying NOT NULL,
title character varying,
studio character varying,
title_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(title)) VIRTUAL HIDDEN,
studio_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(studio)) VIRTUAL HIDDEN,
PRIMARY KEY(albumid));
CREATE SEARCH INDEX albumsindex ON albums(title_tokens, studio_tokens);
以下查詢會在 Title 和 Studio 欄中搜尋含有「blue」和「note」權杖的資料列。包括 Title 欄同時含有「blue」和「note」的資料列、Studio 欄同時含有「blue」和「note」的資料列,以及 Title 欄含有「blue」且 Studio 欄含有「note」的資料列 (反之亦然)。
GoogleSQL
SELECT AlbumId
FROM Albums
WHERE SEARCH(TOKENLIST_CONCAT([AlbumTitle_Tokens, Studio_Tokens]), 'blue note')
PostgreSQL
本範例使用 spanner.search 和 spanner.tokenlist_concat。
SELECT albumid
FROM albums
WHERE spanner.search(spanner.tokenlist_concat(ARRAY[albumtitle_tokens, studio_tokens]), 'blue note')
寫入端和查詢端 TOKENLIST 串連會產生相同的結果。
這兩者之間的選擇,取決於您要權衡磁碟費用和查詢費用。
或者,應用程式可以搜尋多個 TOKENLIST 資料欄,並搭配使用 OR 和 SEARCH 函式:
GoogleSQL
SEARCH(AlbumTitle_Tokens, 'Blue Note') OR SEARCH(Studio_Tokens, 'Blue Note')
PostgreSQL
spanner.search(albumtitle_tokens, 'Blue Note') OR spanner.search(studio_tokens, 'Blue Note')
但這項做法的語意不同。如果 AlbumTitle_Tokens 含有「blue」但不含「note」,或 Studio_Tokens 含有「note」但不含「blue」,系統就不會比對到這些相簿。