検索結果をランク付けする

このページでは、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 が並べ替え順序の確立に使用する関連性スコアとして機能する値を返します。単独で意味を持ちません。スコアが高いほど、クエリとの一致度が高くなります。

通常、queryenhance_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 つのバージョンがあります。部分一致ブーストは、次の場合に適用されます。

  1. TOKENLIST には、クエリの元のキーワードがすべて含まれます。
  2. トークンは、クエリに表示されるのと同じ順序で隣接しています。

連結詞、否定、フレーズに対しては、特別なルールがあります。

  • 否定を含むクエリは、部分一致ブーストを受け取ることができません。
  • 結合を含むクエリは、結合の一部が適切な場所に表示された場合、ブーストの対象となります。
  • フレーズを含むクエリは、そのフレーズが 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 つの上限があります。

  1. 取得深度の上限: スコアリングする行の最大数。
  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 が最も重要なランキング シグナルを使用してインデックスを並べ替える場合に特に効果的です。

次のステップ