本頁面說明 SEARCH
函式和強化查詢模式,這兩者可用於對 Spanner 表格執行全文搜尋查詢。
查詢搜尋索引
Spanner 提供 SEARCH
函式,用於搜尋索引查詢。舉例來說,使用者在應用程式的搜尋框中輸入文字,應用程式會將使用者輸入的內容直接傳送至 SEARCH
函式。SEARCH
函式隨後會使用搜尋索引尋找該文字。
SEARCH
函式需要兩個引數:
- 搜尋索引名稱
- 搜尋查詢
只有在定義搜尋索引時,SEARCH
函式才會運作。SEARCH
函式可與任何任意 SQL 建構體合併,例如篩選器、匯總或聯結。
SEARCH
函式無法用於交易查詢。
下列查詢使用 SEARCH
函式,傳回標題中含有 friday
或 monday
的所有專輯:
GoogleSQL
SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, 'friday OR monday')
PostgreSQL
本範例使用 spanner.search。
SELECT albumid
FROM albums
WHERE spanner.search(albumtitle_tokens, 'friday OR monday')
搜尋查詢
根據預設,搜尋查詢會使用原始搜尋查詢語法。您可以使用 SEARCH
dialect
引數指定替代語法。
rquery 方言
預設方言為「原始搜尋查詢」。Spanner 使用名為 rquery 的特定領域語言 (DSL)。
將輸入的搜尋查詢拆解為不同字詞時,rquery 語言會遵循與純文字權杖化工具相同的規則。包括亞洲語言的區隔。
如要瞭解如何使用 rquery,請參閱 rquery 語法。
words dialect
「dialect」一詞類似於「rquery」,但更簡單。不會使用任何特殊運算子。舉例來說,OR
會被視為搜尋字詞,而非不相交運算子。雙引號會被視為標點符號,而非片語搜尋,因此會遭到忽略。
使用「dialect」一詞時,AND
會隱含套用至所有字詞,且在比對期間為必要條件。將輸入的搜尋查詢拆解為字詞時,這項工具會遵循與純文字權杖化工具相同的規則。
如要瞭解如何使用 words 方言,請參閱 words 語法。
words_phrase 方言
words_phrase 方言不會使用任何特殊運算子,所有字詞都會視為片語,也就是字詞必須相鄰,且順序與指定順序相同。
與 rquery 相同,words_phrase 方言在將輸入的搜尋查詢分割為字詞時,會遵循與純文字權杖化工具相同的規則。
如要瞭解如何使用 words_phrase 方言,請參閱 words phrase 語法。
強化查詢模式
Spanner 提供兩種全文搜尋模式:基本權杖式搜尋和更進階的 enhance_query
模式。啟用後,enhance_query
會擴充搜尋查詢,納入相關字詞和同義詞,提高找到相關結果的機率。
如要啟用這個選項,請在 SEARCH
函式中設定選用引數 enhance_query=>true
。舉例來說,搜尋查詢 hotl cal
會比對到專輯 Hotel California
。
GoogleSQL
SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, 'hotl cal', enhance_query=>true)
PostgreSQL
SELECT albumid
FROM albums
WHERE spanner.search(albumtitle_tokens, 'hotl cal', enhance_query=>true)
enhance_query
模式是查詢時間選項。這不會影響權杖化。
無論是否使用 enhance_query
,您都可以使用相同的搜尋索引。
Google 會持續改良查詢強化演算法,因此,隨著時間經過,使用 enhance_query == true
的查詢可能會產生略有不同的結果。
啟用 enhance_query
模式後,SEARCH
函式搜尋的字詞數量可能會增加,導致延遲時間稍微延長。
舉例來說,下列查詢會使用三秒逾時,如果 enhance_query
無法使用,查詢就會失敗:
GoogleSQL
@{require_enhance_query=true, enhance_query_timeout_ms=3000}
SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, 'fast car', enhance_query=>true)
PostgreSQL
/*@require_enhance_query=true, enhance_query_timeout_ms=3000*/
SELECT albumid
FROM albums
WHERE spanner.search(albumtitle_tokens, 'fast car', enhance_query=>true)
SQL 查詢規定
SQL 查詢必須符合多項條件,才能使用搜尋索引。 如果不符合這些條件,查詢會使用替代查詢計畫,如果沒有替代計畫,查詢就會失敗。
查詢必須符合下列條件:
SEARCH 函式和
SEARCH_SUBSTRING
函式需要搜尋索引。針對基本資料表或次要索引的查詢,Spanner 不支援這些函式。已分割的索引必須在查詢的
WHERE
子句中,將所有分割資料欄繫結至等號條件。舉例來說,如果搜尋索引定義為
PARTITION BY x, y
,查詢的x = <parameter or constant> AND y = <parameter or constant>
WHERE
子句就必須有連詞。如果缺少這類條件,查詢最佳化工具就不會考慮該搜尋索引。SEARCH
和SEARCH_SUBSTRING
運算子參照的所有TOKENLIST
欄都必須在同一個搜尋索引中建立索引。舉例來說,請參考下列資料表和索引定義:
GoogleSQL
CREATE TABLE Albums ( AlbumId STRING(MAX) NOT NULL, AlbumTitle STRING(MAX), AlbumStudio STRING(MAX), AlbumTitle_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN, AlbumStudio_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumStudio)) HIDDEN ) PRIMARY KEY(AlbumId); CREATE SEARCH INDEX AlbumsTitleIndex ON Albums(AlbumTitle_Tokens); CREATE SEARCH INDEX AlbumsStudioIndex ON Albums(AlbumStudio_Tokens);
PostgreSQL
CREATE TABLE albums ( albumid character varying NOT NULL, albumtitle character varying, albumstudio character varying, albumtitle_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(albumtitle)) VIRTUAL HIDDEN, albumstudio_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(albumstudio)) VIRTUAL HIDDEN, PRIMARY KEY(albumid)); CREATE SEARCH INDEX albumstitleindex ON albums(albumtitle_tokens); CREATE SEARCH INDEX albumsstudioindex ON albums(albumstudio_tokens);
下列查詢會失敗,因為沒有單一搜尋索引可同時為
AlbumTitle_Tokens
和AlbumStudio_Tokens
建立索引:GoogleSQL
SELECT AlbumId FROM Albums WHERE SEARCH(AlbumTitle_Tokens, @p1) AND SEARCH(AlbumStudio_Tokens, @p2)
PostgreSQL
這個範例使用查詢參數
$1
和$2
,分別繫結至「fast car」和「blue note」。SELECT albumid FROM albums WHERE spanner.search(albumtitle_tokens, $1) AND spanner.search(albumstudio_tokens, $2)
如果排序順序資料欄可為空值,結構定義和查詢都必須排除排序順序資料欄為空值的資料列。詳情請參閱「搜尋索引排序順序」。
如果搜尋索引經過 NULL 篩選,查詢必須包含索引中使用的相同 NULL 篩選運算式。詳情請參閱「已篩除 NULL 的搜尋索引」。
搜尋索引和搜尋函式通常用於唯讀交易。如果應用程式需求允許過時結果,您或許可以執行搜尋查詢,並將過時時間設為 10 秒以上,藉此縮短延遲時間。詳情請參閱「讀取過時資料」。對於分散到多個索引分割的搜尋查詢,這項功能特別實用。
建議不要在讀寫交易中使用搜尋索引和搜尋函式。執行期間,搜尋查詢會鎖定整個索引分區;因此,讀寫交易中的搜尋查詢率過高可能會導致鎖定衝突,進而造成延遲尖峰。根據預設,讀寫交易不會自動選取搜尋索引。如果查詢在讀取/寫入交易中強制使用搜尋索引,預設會失敗。如果查詢包含任何搜尋函式,也會失敗。您可以使用 GoogleSQL @{ALLOW_SEARCH_INDEXES_IN_TRANSACTION=TRUE}
陳述式層級提示覆寫這項行為 (但查詢仍可能發生鎖定衝突)。
符合索引資格條件後,查詢最佳化工具會嘗試加速處理非文字查詢條件 (例如 Rating > 4
)。如果搜尋索引未包含適當的 TOKENLIST
欄,系統就不會加速處理條件,條件仍會是剩餘條件。
查詢參數
搜尋查詢引數可指定為常值或查詢參數。如果引數允許查詢參數值,建議使用查詢參數進行全文搜尋,而非字串常值。
選取指數
Spanner 通常會使用以成本為準的模擬方式,為查詢選取最有效率的索引。不過,FORCE_INDEX
提示會明確指示 Spanner 使用特定搜尋索引。舉例來說,以下說明如何強制 Spanner 使用 AlbumsIndex
:
GoogleSQL
SELECT AlbumId
FROM Albums @{FORCE_INDEX=AlbumsIndex}
WHERE SEARCH(AlbumTitle_Tokens, "fifth symphony")
PostgreSQL
SELECT albumid
FROM albums/*@force_index=albumsindex*/
WHERE spanner.search(albumtitle_tokens, 'fifth symphony')
如果指定的搜尋索引不符合資格,即使有其他符合資格的搜尋索引,查詢也會失敗。
搜尋結果中的摘要
網頁摘要是從指定字串擷取的文字片段,可讓使用者瞭解搜尋結果的內容,以及結果與查詢內容的相關性。
舉例來說,Gmail 會使用摘要指出電子郵件中符合搜尋查詢的部分:
讓資料庫產生程式碼片段有幾個優點:
- 便利性:您不必實作邏輯,即可根據搜尋查詢產生摘要。
- 效率:程式碼片段可減少伺服器輸出大小。
SNIPPET
函式會建立程式碼片段。並傳回原始字串值的相關部分,以及要醒目顯示的字元位置。然後,用戶端可以選擇如何向使用者顯示程式碼片段 (例如使用醒目顯示或粗體文字)。
舉例來說,下列程式碼會使用 SNIPPET
從 AlbumTitle
擷取文字:
GoogleSQL
SELECT AlbumId, SNIPPET(AlbumTitle, "Fast Car")
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, "Fast Car")
PostgreSQL
本範例使用 spanner.snippet。
SELECT albumid, spanner.snippet(albumtitle, 'Fast Car')
FROM albums
WHERE spanner.search(albumtitle_tokens, 'Fast Car')
後續步驟
- 瞭解如何排序搜尋結果。
- 瞭解如何執行子字串搜尋。
- 瞭解如何將搜尋結果分頁。
- 瞭解如何混合使用全文和非文字查詢。
- 瞭解如何搜尋多個資料欄。