本頁說明如何在 Spanner 中,為全文搜尋結果排名。
Spanner 支援計算主題性分數,可做為建立複雜排名函式的建構區塊。這些分數會根據查詢字詞頻率和其他可自訂選項,計算結果與查詢的關聯性。
以下範例說明如何使用 SCORE
函式執行排名搜尋:
GoogleSQL
SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, "fifth symphony")
ORDER BY SCORE(AlbumTitle_Tokens, "fifth symphony") DESC
PostgreSQL
本範例使用 spanner.search
和 spanner.score
。
SELECT albumid
FROM albums
WHERE spanner.search(albumtitle_tokens, 'fifth symphony')
ORDER BY spanner.score(albumtitle_tokens, 'fifth symphony') DESC
使用 SCORE
函式為查詢字詞評分
SCORE
函式會計算每個查詢字詞的分數,然後合併這些分數。每個字詞的分數大致上是根據字詞頻率 - 轉換文件頻率 (TF/IDF) 計算而得。分數是記錄最終排序的其中一個要素。查詢會將這項信號與其他信號合併,例如新鮮度會調控主題分數。
在目前的實作項目中,只有在使用 enhance_query=>true
時,才能取得 TF/IDF 的 IDF 部分。這項工具會根據 Google 搜尋使用的完整網路語料庫,而非特定搜尋索引,計算字詞的相對頻率。如果未啟用 rquery 強化功能,評分只會使用詞頻 (TF) 元件 (也就是 IDF 字詞設為 1)。
SCORE
函式會傳回相關分數,Spanner 會根據這些分數建立排序順序。沒有獨立意義。分數越高,表示與查詢的相符程度越高。
通常 SEARCH
和 SCORE
函式中的 query
和 enhance_query
等引數會相同,確保擷取和排序作業的一致性。
建議您使用這些引數搭配查詢參數,而非字串常值,並在 SEARCH
和 SCORE
函式中指定相同的查詢參數。
為多個資料欄評分
Spanner 會使用 SCORE
函式,個別為每個欄位評分。然後查詢會將這些個別分數合併。常見做法是加總個別分數,然後根據使用者提供的欄位權重 (使用 SQL 查詢參數提供) 提高分數。
舉例來說,下列查詢會合併兩個 SCORE
函式的輸出內容:
GoogleSQL
SELECT AlbumId
FROM Albums
WHERE SEARCH(Title_Tokens, @p1) AND SEARCH(Studio_Tokens, @p2)
ORDER BY SCORE(Title_Tokens, @p1) * @titleweight + SCORE(Studio_Tokens, @p2) * @studioweight
LIMIT 25
PostgreSQL
本範例使用查詢參數 $1
和 $2
,分別繫結至「fifth symphony」和「blue note」。
SELECT albumid
FROM albums
WHERE spanner.search(title_tokens, $1) AND spanner.search(studio_tokens, $2)
ORDER BY spanner.score(title_tokens, $1) * $titleweight
+ spanner.score(studio_tokens, $2) * $studioweight
LIMIT 25
以下範例會新增兩個提升參數:
- 新鮮度 (
FreshnessBoost
) 會提高分數,(1 + @freshnessweight * GREATEST(0, 30 - DaysOld) / 30)
- 熱門程度(
PopularityBoost
) 會將分數乘以係數(1 + IF(HasGrammy, @grammyweight, 0)
,藉此提高分數。
為了方便閱讀,查詢會使用 WITH
運算子。
GoogleSQL
SELECT AlbumId
FROM Albums
WHERE SEARCH(Title_Tokens, @p1) AND SEARCH(Studio_Tokens, @p2)
ORDER BY WITH(
TitleScore AS SCORE(Title_Tokens, @p1) * @titleweight,
StudioScore AS SCORE(Studio_Tokens, @p2) * @studioweight,
DaysOld AS (UNIX_MICROS(CURRENT_TIMESTAMP()) - ReleaseTimestamp) / 8.64e+10,
FreshnessBoost AS (1 + @freshnessweight * GREATEST(0, 30 - DaysOld) / 30),
PopularityBoost AS (1 + IF(HasGrammy, @grammyweight, 0)),
(TitleScore + StudioScore) * FreshnessBoost * PopularityBoost)
LIMIT 25
PostgreSQL
本範例使用查詢參數 $1
、$2
、$3
、$4
、$5
和 $6
,這些參數分別繫結至 titlequery
、studioquery
、titleweight
、studioweight
、grammyweight
和 freshnessweight
指定的值。
SELECT albumid
FROM
(
SELECT
albumid,
spanner.score(title_tokens, $1) * $3 AS titlescore,
spanner.score(studio_tokens, $2) * $4 AS studioscore,
(extract(epoch FROM current_timestamp) * 10e+6 - releasetimestamp) / 8.64e+10 AS daysold,
(1 + CASE WHEN hasgrammy THEN $5 ELSE 0 END) AS popularityboost
FROM albums
WHERE spanner.search(title_tokens, $1) AND spanner.search(studio_tokens, $2)
) AS subquery
ORDER BY (subquery.TitleScore + subquery.studioscore)
* (1 + $6 * greatest(0, 30 - subquery.daysold) / 30) * subquery.popularityboost
LIMIT 25
TOKENLIST_CONCAT
也可用於搜尋和評分,在適當情況下簡化查詢。
GoogleSQL
SELECT AlbumId
FROM Albums
WHERE SEARCH(TOKENLIST_CONCAT([Title_Tokens, Studio_Tokens]), @p)
ORDER BY SCORE(TOKENLIST_CONCAT([Title_Tokens, Studio_Tokens]), @p)
LIMIT 25
PostgreSQL
本範例使用 spanner.tokenlist_concat
。查詢參數 $1
會繫結至「blue note」。
SELECT albumid
FROM albums
WHERE spanner.search(spanner.tokenlist_concat(ARRAY[title_tokens, studio_tokens]), $1)
ORDER BY spanner.score(spanner.tokenlist_concat(ARRAY[title_tokens, studio_tokens]), $1)
LIMIT 25
提高查詢順序相符程度
如果值包含查詢字詞,且順序與查詢中的字詞相同,Spanner 會對 SCORE
函式的輸出內容套用乘法提升。這項加成有兩種版本:部分相符和完全相符。在下列情況下,系統會套用部分相符的提升效果:
TOKENLIST
包含查詢中的所有原始字詞。- 權杖彼此相鄰,且順序與查詢中顯示的順序相同。
連詞、否定詞和片語有特定的特殊規則:
- 含有否定詞的查詢無法獲得部分相符的提升。
- 如果連詞的一部分出現在適當位置,含有連詞的查詢就會獲得加成。
- 如果查詢中的詞組出現在
TOKENLIST
中,且查詢中詞組左側的字詞出現在TOKENLIST
中詞組左側,且查詢中詞組右側的字詞出現在TOKENLIST
中詞組右側,則含有該詞組的查詢會獲得加成。
如果先前的所有規則都成立,且查詢中的第一個和最後一個符記與文件中的第一個和最後一個符記相同,Spanner 就會套用完全比對的提升效果。
範例文件:Bridge Over Troubled Water
查詢 | 已套用 Boost |
---|---|
Bridge Troubled | 不加成 |
Bridge Over - other water | 不加成 |
Bridge (Over OR Troubled) Water | 不加成 |
Bridge Over | 部分提升 |
Bridge Over (Troubled OR Water) | 部分提升 |
Bridge Over Troubled Water | 精確提升 |
Bridge Over Troubled Water | 精確提升 |
Bridge ("Over Troubled" OR missingterm) Water | 精確提升 |
限制擷取深度
搜尋索引通常包含數百萬份文件。如果查詢的述詞選擇性較低,就不適合對所有結果進行排序。評分查詢通常有兩項限制:
- 擷取深度限制:要評分的資料列數量上限。
- 結果集大小限制:查詢應傳回的資料列數量上限 (通常是頁面大小)。
查詢可使用 SQL 子查詢限制擷取深度:
GoogleSQL
SELECT *
FROM (
SELECT AlbumId, Title_Tokens
FROM Albums
WHERE SEARCH(Title_Tokens, @p1)
ORDER BY ReleaseTimestamp DESC
LIMIT @retrieval_limit
)
ORDER BY SCORE(Title_Tokens, @p1)
LIMIT @page_size
PostgreSQL
這個範例使用查詢參數 $1
、$2
和 $3
,這些參數分別繫結至 title_query
、retrieval_limit
和 page_size
指定的值。
SELECT *
FROM (
SELECT albumid, title_tokens
FROM albums
WHERE spanner.search(title_tokens, $1)
ORDER BY releasetimestamp DESC
LIMIT $2
) AS subquery
ORDER BY spanner.score(subquery.title_tokens, $1)
LIMIT $3
如果 Spanner 使用最重要的排名信號排序索引,這項做法特別有效。
後續步驟
- 瞭解全文搜尋查詢。
- 瞭解如何執行子字串搜尋。
- 瞭解如何將搜尋結果分頁。
- 瞭解如何混合使用全文和非文字查詢。
- 瞭解如何搜尋多個資料欄。