Suchergebnisse ranken

Auf dieser Seite wird beschrieben, wie Sie Suchergebnisse für Volltextsuchen in Spanner sortieren.

Spanner unterstützt die Berechnung eines Themenwerts, der als Baustein für die Erstellung komplexer Rankingfunktionen dient. Anhand dieser Bewertungen wird die Relevanz eines Ergebnisses für eine Suchanfrage berechnet. Dabei werden die Häufigkeit des Suchbegriffs und andere anpassbare Optionen berücksichtigt.

Im folgenden Beispiel wird gezeigt, wie Sie mit der Funktion SCORE eine sortierte Suche durchführen:

GoogleSQL

SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, "fifth symphony")
ORDER BY SCORE(AlbumTitle_Tokens, "fifth symphony") DESC

PostgreSQL

In diesem Beispiel wird spanner.search mit spanner.score verwendet.

SELECT albumid
FROM albums
WHERE spanner.search(albumtitle_tokens, 'fifth symphony')
ORDER BY spanner.score(albumtitle_tokens, 'fifth symphony') DESC

Suchbegriffe mit der Funktion SCORE bewerten

Die Funktion SCORE berechnet einen Wert für jeden Suchbegriff und kombiniert dann die Werte. Die Punktzahl pro Begriff basiert grob auf der Begriffshäufigkeit – umgekehrte Dokumenthäufigkeit (TF/IDF). Die Bewertung ist eine Komponente der endgültigen Sortierung eines Eintrags. Bei der Abfrage wird er mit anderen Signalen kombiniert, z. B. der Aktualität, die den Themenwert beeinflusst.

In der aktuellen Implementierung ist der IDF-Teil von TF/IDF nur verfügbar, wenn enhance_query=>true verwendet wird. Dabei wird die relative Häufigkeit von Wörtern anhand des gesamten Webkorpus berechnet, der von der Google Suche verwendet wird, und nicht anhand eines bestimmten Suchindexes. Wenn die R-Suchanfrage-Optimierung nicht aktiviert ist, wird bei der Bewertung nur die Komponenten „Begriffshäufigkeit“ (TF) verwendet. Das heißt, der IDF-Begriff ist auf „1“ gesetzt.

Die Funktion SCORE gibt Werte zurück, die als Relevanzbewertungen dienen, anhand derer Spanner eine Sortierreihenfolge festlegt. Sie haben keine eigenständige Bedeutung. Je höher der Wert, desto besser die Übereinstimmung mit der Suchanfrage.

Normalerweise sind Argumente wie query und enhance_query für die Funktionen SEARCH und SCORE identisch, um für Konsistenz beim Abrufen und Rangieren zu sorgen.

Wir empfehlen, diese Argumente mit Abfrageparametern anstelle von Stringliteralen zu verwenden und dieselben Abfrageparameter in den Funktionen SEARCH und SCORE anzugeben.

Mehrere Spalten bewerten

In Spanner wird die Funktion SCORE verwendet, um jedes Feld einzeln zu bewerten. Diese einzelnen Bewertungen werden dann in der Abfrage kombiniert. Eine gängige Methode besteht darin, die einzelnen Bewertungen zu summieren und dann gemäß den von Nutzern angegebenen Feldgewichten zu erhöhen (die mit SQL-Abfrageparametern angegeben werden).

In der folgenden Abfrage wird beispielsweise die Ausgabe von zwei SCORE-Funktionen kombiniert:

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

In diesem Beispiel werden die Abfrageparameter $1 und $2 verwendet, die jeweils an „fünfte Symphonie“ und „blaue Note“ gebunden sind.

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

Im folgenden Beispiel werden zwei Boost-Parameter hinzugefügt:

  • Die Aktualität (FreshnessBoost) erhöht die Punktzahl um (1 + @freshnessweight * GREATEST(0, 30 - DaysOld) / 30)
  • Mit „Beliebtheit“ (PopularityBoost) wird der Wert durch Multiplikation mit dem Faktor (1 + IF(HasGrammy, @grammyweight, 0) erhöht.

Der Operator WITH wird verwendet, um die Lesbarkeit der Abfrage zu verbessern.

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

In diesem Beispiel werden die Abfrageparameter $1, $2, $3, $4, $5 und $6 verwendet, die jeweils an die Werte für titlequery, studioquery, titleweight, studioweight, grammyweight und freshnessweight gebunden sind.

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 kann sowohl bei der Suche als auch bei der Bewertung verwendet werden, um Abfragen bei Bedarf zu vereinfachen.

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

In diesem Beispiel wird spanner.tokenlist_concat verwendet. Der Abfrageparameter $1 ist an „blaue Notiz“ gebunden.

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

Abfragereihenfolge-Übereinstimmungen optimieren

Spanner erhöht die Ausgabe der SCORE-Funktion für Werte, die die Suchbegriffe in derselben Reihenfolge enthalten, in der sie in der Abfrage erscheinen, um einen Multiplikator. Es gibt zwei Versionen dieses Boosts: teilweise Übereinstimmung und genaue Übereinstimmung. Ein teilweiser Abgleich wird angewendet, wenn:

  1. TOKENLIST enthält alle ursprünglichen Begriffe in der Abfrage.
  2. Die Tokens sind nebeneinander und in derselben Reihenfolge wie in der Abfrage.

Für Konjunktionen, Negationen und Wortgruppen gelten bestimmte Sonderregeln:

  • Eine Suchanfrage mit einer Verneinung kann keinen Zuschlag für teilweise Übereinstimmungen erhalten.
  • Eine Suchanfrage mit einer Konjunktion wird gesteigert, wenn ein Teil der Konjunktion an den entsprechenden Stellen erscheint.
  • Eine Suchanfrage mit einer Wortgruppe wird optimiert, wenn die Wortgruppe in der TOKENLIST enthalten ist und der Begriff links von der Wortgruppe in der Suchanfrage links von der Wortgruppe in der TOKENLIST steht. Gleiches gilt für den Begriff rechts von der Wortgruppe.

Spanner wendet einen Zuschlag für die genaue Übereinstimmung an, wenn alle vorherigen Regeln wahr sind und das erste und das letzte Token in der Abfrage das erste und das letzte Token im Dokument sind.

Beispieldokument: Bridge Over Troubled Water

Abfrage Booster angewendet
Bridge Troubled ohne Steigerung
Brücke über – anderes Gewässer ohne Steigerung
Brücke über (oder unruhiges) Wasser ohne Steigerung
Bridge Over Teilweise Steigerung
Brücke über (bewegtes Wasser ODER Wasser) Teilweise Steigerung
Bridge Over Troubled Water Steigerung bei genau passenden Keywords
Brücke „über unruhiges Wasser“ genau passende Keywords
Brücke („Über stürmisches“ ODER missingterm) Wasser genau passende Keywords

Tiefe der Datenabfrage begrenzen

Suchindexe enthalten oft Millionen von Dokumenten. Bei Abfragen, bei denen die Prädikate eine geringe Selektivität haben, ist es nicht praktikabel, alle Ergebnisse zu sortieren. Für Bewertungsanfragen gelten in der Regel zwei Limits:

  1. Retrieval depth limit (Limit für die Abruftiefe): Die maximale Anzahl der Zeilen, die bewertet werden sollen.
  2. Größenlimit für Ergebnissatz: Die maximale Anzahl von Zeilen, die die Abfrage zurückgeben soll (in der Regel die Seitengröße).

Mit SQL-Unterabfragen können Sie die Abruftiefe von Abfragen einschränken:

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

In diesem Beispiel werden die Abfrageparameter $1, $2 und $3 verwendet, die jeweils an die Werte gebunden sind, die für title_query, retrieval_limit und page_size angegeben sind.

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

Das funktioniert besonders gut, wenn Spanner das wichtigste Ranking-Signal zum Sortieren des Index verwendet.

Nächste Schritte