Cette page explique comment classer les résultats de recherche pour les recherches en texte intégral dans Spanner.
Spanner permet de calculer un score de pertinence, qui constitue un élément de base pour créer des fonctions de classement sophistiquées. Ces scores calculent la pertinence d'un résultat par rapport à une requête, en fonction de la fréquence des termes de la requête et d'autres options personnalisables.
L'exemple suivant montre comment effectuer une recherche classée à l'aide de la fonction SCORE
:
GoogleSQL
SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, "fifth symphony")
ORDER BY SCORE(AlbumTitle_Tokens, "fifth symphony") DESC
PostgreSQL
Cet exemple utilise spanner.search
avec spanner.score
.
SELECT albumid
FROM albums
WHERE spanner.search(albumtitle_tokens, 'fifth symphony')
ORDER BY spanner.score(albumtitle_tokens, 'fifth symphony') DESC
Évaluer les termes de requête avec la fonction SCORE
La fonction SCORE
calcule un score pour chaque terme de requête, puis combine les scores. Le score par terme est basé approximativement sur la fréquence du terme – fréquence inverse des documents (TF/IDF). Le score est l'un des composants de l'ordre final d'un enregistrement. La requête le combine à d'autres signaux, tels que la fraîcheur qui module le score de pertinence.
Dans l'implémentation actuelle, la partie IDF de TF/IDF n'est disponible que lorsque enhance_query=>true
est utilisé. Il calcule la fréquence relative des mots en fonction du corpus Web complet utilisé par la recherche Google, et non d'un index de recherche spécifique. Si l'amélioration de la requête r n'est pas activée, l'évaluation n'utilise que la composante fréquence des termes (TF) (c'est-à-dire que le terme IDF est défini sur 1).
La fonction SCORE
renvoie des valeurs qui servent de scores de pertinence que Spanner utilise pour établir un ordre de tri. Elles n'ont aucune signification autonome. Plus le score est élevé, plus la correspondance est bonne.
En règle générale, les arguments tels que query
et enhance_query
sont les mêmes pour les fonctions SEARCH
et SCORE
afin de garantir la cohérence de la récupération et du classement.
La méthode recommandée consiste à utiliser ces arguments avec des paramètres de requête plutôt que des littéraux de chaîne, et à spécifier les mêmes paramètres de requête dans les fonctions SEARCH
et SCORE
.
Évaluer plusieurs colonnes
Spanner utilise la fonction SCORE
pour évaluer chaque champ individuellement. La requête combine ensuite ces scores individuels. Pour ce faire, il est courant de résumer les scores individuels, puis de les renforcer en fonction des pondérations de champ fournies par l'utilisateur (qui sont fournies à l'aide de paramètres de requête SQL).
Par exemple, la requête suivante combine la sortie de deux fonctions 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
Cet exemple utilise les paramètres de requête $1
et $2
, qui sont liés respectivement à "cinquième symphonie" et "note bleue".
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
L'exemple suivant ajoute deux paramètres de boost:
- La fraîcheur (
FreshnessBoost
) augmente le score de(1 + @freshnessweight * GREATEST(0, 30 - DaysOld) / 30)
- Popularity(
PopularityBoost
) augmente le score en le multipliant par le facteur(1 + IF(HasGrammy, @grammyweight, 0)
.
Pour plus de lisibilité, la requête utilise l'opérateur 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
Cet exemple utilise les paramètres de requête $1
, $2
, $3
, $4
, $5
et $6
, qui sont liés aux valeurs spécifiées pour titlequery
, studioquery
, titleweight
, studioweight
, grammyweight
et freshnessweight
, respectivement.
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
peut également être utilisé à la fois pour la recherche et l'évaluation afin de simplifier les requêtes lorsque cela est approprié.
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
Cet exemple utilise spanner.tokenlist_concat
.
Le paramètre de requête $1
est lié à "note bleue".
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
Booster les correspondances d'ordre de requête
Spanner applique un boost multiplicatif à la sortie de la fonction SCORE
pour les valeurs contenant les termes de requête dans le même ordre qu'ils apparaissent dans la requête. Il existe deux versions de cette amélioration: la correspondance partielle et la correspondance exacte. Un boost de correspondance partielle est appliqué lorsque:
TOKENLIST
contient tous les termes d'origine de la requête.- Les jetons sont adjacents les uns aux autres et dans le même ordre qu'ils apparaissent dans la requête.
Il existe certaines règles spéciales pour les conjonctions, les négations et les expressions:
- Une requête contenant une négation ne peut pas bénéficier d'un boost de correspondance partielle.
- Une requête avec une conjonction reçoit un coup de pouce si une partie de la conjonction apparaît aux endroits appropriés.
- Une requête contenant une expression est améliorée si l'expression apparaît dans
TOKENLIST
, et que le terme situé à gauche de l'expression dans la requête apparaît à gauche de l'expression dansTOKENLIST
. Il en va de même pour le terme situé à droite de l'expression.
Spanner applique un boost de correspondance exacte lorsque toutes les règles précédentes sont vraies et que les premiers et derniers jetons de la requête sont les premiers et derniers jetons du document.
Exemple de document: Bridge Over Troubled Water
Requête | Boost appliqué |
---|---|
Bridge Troubled | aucune amélioration |
Pont surplombant un autre cours d'eau | aucune amélioration |
Pont (sur ou en panne) sur l'eau | aucune amélioration |
Bridge Over | amplification partielle |
Pont (eau trouble ou en crue) | amplification partielle |
Bridge Over Troubled Water | boost exact |
Pont "Over Troubled" Water | boost exact |
Pont ("Over Troubled" OR missingterm) Eau | boost exact |
Limiter la profondeur de récupération
Les index de recherche contiennent souvent des millions de documents. Pour les requêtes dont les prédicats ont une faible sélectivité, il est peu pratique de classer tous les résultats. Les requêtes d'évaluation ont généralement deux limites:
- Limite de profondeur de récupération: nombre maximal de lignes à évaluer.
- Limite de taille du jeu de résultats: nombre maximal de lignes que la requête doit renvoyer (généralement la taille de la page).
Les requêtes peuvent limiter la profondeur de récupération à l'aide de sous-requêtes 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
Cet exemple utilise les paramètres de requête $1
, $2
et $3
, qui sont liés aux valeurs spécifiées pour title_query
, retrieval_limit
et page_size
, respectivement.
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
Cette approche est particulièrement efficace si Spanner utilise le signal de classement le plus important pour trier l'index.
Étape suivante
- En savoir plus sur les requêtes de recherche en texte intégral
- Découvrez comment effectuer une recherche de sous-chaîne.
- Découvrez comment paginer les résultats de recherche.
- Découvrez comment combiner des requêtes en texte intégral et non textuelles.
- Découvrez comment effectuer une recherche dans plusieurs colonnes.