このページでは、Spanner で全文検索の検索結果をランク付けする方法について説明します。
Spanner は、トピカリティ スコアの計算をサポートしています。これは、高度なランキング関数を作成するための構成要素となります。これらのスコアは、クエリ語句の頻度やその他のカスタマイズ可能なオプションに基づいて、クエリに対する結果の関連性を計算します。
次の例は、ランキング検索を示しています。
SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, "fifth symphony")
ORDER BY SCORE(AlbumTitle_Tokens, "fifth symphony") DESC
SCORE
関数を使用してクエリ語句にスコアを付ける
SCORE
関数は、各クエリ語句のスコアを計算し、スコアを結合します。用語ごとのスコアは、おおまかに 用語頻度 - 逆文書頻度(TF/IDF)に基づいています。スコアは、レコードの最終的な順序付けをするコンポーネントの 1 つです。このクエリは、トピカリティ スコアの調整による更新頻度など、他のシグナルと組み合わせて使用されます。
現在の実装では、TF/IDF の IDF 部分は enhance_query=>true
が使用されている場合にのみ使用できます。特定の検索インデックスではなく、Google 検索で使用されるウェブ コーパス全体に基づいて、単語の相対頻度を計算します。rquery 拡張機能が有効になっていない場合、スコアリングでは語句頻度(TF)コンポーネントのみが使用されます(つまり、IDF 語句は 1 に設定されます)。
SCORE
関数は、Spanner が並べ替え順序の確立に使用する関連性スコアとして機能する値を返します。単独で意味を持ちません。スコアが高いほど、クエリとの一致度が高くなります。
通常、query
や enhance_query
などの引数は、SEARCH
関数と SCORE
関数の両方で同じ値にすることで、情報の取得とランキングの整合性を保ちます。
推奨される方法は、これらの引数を文字列リテラルではなくクエリ パラメータで使用し、SEARCH
関数と SCORE
関数で同じクエリ パラメータを指定することです。
複数の列をスコアリングする
Spanner は SCORE
関数を使用して、各フィールドを個別にスコアリングします。クエリは、これらの個々のスコアを組み合わせます。この一般的な処理として、個々のスコアを合計し、ユーザー指定のフィールド重み(SQL クエリ パラメータを使用して指定)に従ってスコアをブーストする方法が適用されます。
たとえば、次のクエリは 2 つの SCORE
関数の出力を結合します。
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
次の例では、2 つのブースト パラメータを追加します。
- 最新度(
FreshnessBoost
)は(1 + @freshnessweight * GREATEST(0, 30 - DaysOld) / 30)
でスコアを増加します。 - 人気度(
PopularityBoost
)は、スコアに係数(1 + IF(HasGrammy, @grammyweight, 0)
を掛けてスコアを増加します。
読みやすくするために、このクエリでは WITH
演算子を使用しています。
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
必要に応じて、検索とスコアリングの両方で TOKENLIST_CONCAT
を使用して、クエリを簡素化することもできます。
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
クエリ順序の一致をブーストする
クエリ語句がクエリでの表示と同じ順序で含まれている値については、トピカリティ スコアに乗算ブーストを適用できます。このブーストには、部分一致と完全一致の 2 つのバージョンがあります。部分一致ブーストは、次の場合に適用されます。
TOKENLIST
には、クエリの元のキーワードがすべて含まれます。- トークンは、クエリに表示されるのと同じ順序で隣接しています。
連結詞、否定、フレーズに対しては、特別なルールがあります。
- 否定を含むクエリは、部分一致ブーストを受け取ることができません。
- 結合を含むクエリは、結合の一部が適切な場所に表示された場合、ブーストの対象となります。
- フレーズを含むクエリは、そのフレーズが
TOKENLIST
に含まれ、クエリ内のフレーズ左側のキーワードがTOKENLIST
内のフレーズ左側に含まれる場合にブーストされます。フレーズ右側のキーワードにも同様の処理が適用されます。
上記のすべてのルールが true の場合、Spanner は完全一致ブーストを適用します。クエリの最初のトークンと最後のトークンは、ドキュメントの最初のトークンと最後のトークンです。
ドキュメントの例: Bridge Over Troubled Water
クエリ | 適用されているブースト |
---|---|
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 | 完全一致ブースト |
取得深度を制限する
検索インデックスには、数百万ものドキュメントが含まれていることがよくあります。述語の選択性が低いクエリでは、すべての結果をランク付けすることは現実的ではありません。スコアリング クエリには通常、次の 2 つの上限があります。
- 取得深度の上限: スコアリングする行の最大数。
- 結果セットのサイズの上限: クエリが返す行の最大数(通常はページサイズ)。
クエリでは、SQL サブクエリを使用して取得深度を制限できます。
SELECT *
FROM (
SELECT AlbumId
FROM Albums
WHERE SEARCH(Title_Tokens, @p1)
ORDER BY ReleaseTimestamp DESC
LIMIT @retrieval_limit
)
ORDER BY SCORE(Title_Tokens, @p1)
LIMIT @page_size
これは、Spanner が最も重要なランキング シグナルを使用してインデックスを並べ替える場合に特に効果的です。
次のステップ
- 全文検索クエリについて学習する。
- 部分文字列検索を行う方法を学習する。
- 検索結果をページ分けする方法を学習する。
- 全文クエリと非テキストクエリを組み合わせる方法を学習する。
- 複数の列を検索する方法について学ぶ。