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 d'actualité, 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
Attribuer un score aux termes de requête avec la fonction SCORE
La fonction SCORE calcule un score pour chaque terme de la requête, puis combine les scores. Le score par terme est approximativement basé sur la fréquence du terme – fréquence inverse dans les documents (TF/IDF). Le score est l'un des composants de l'ordre final d'un enregistrement. La requête la combine avec d'autres signaux, tels que la fraîcheur, qui modulent le score d'actualité.
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 de l'ensemble du corpus Web utilisé par la recherche Google, plutôt que d'un index de recherche spécifique. Si l'amélioration rquery n'est pas activée, l'évaluation n'utilise que le composant de 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. Ils n'ont pas de signification propre. Plus le score est élevé, plus la correspondance avec la requête est bonne.
En général, les arguments tels que query et enhance_query sont identiques dans les fonctions SEARCH et SCORE pour garantir la cohérence de la récupération et du classement.
Pour ce faire, nous vous recommandons d'utiliser ces arguments avec des paramètres de requête plutôt que des littéraux de chaîne, et de 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, une méthode courante consiste à additionner les scores individuels, puis à les booster 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 le résultat de deux fonctions SCORE :
GoogleSQL
SELECT AlbumId
FROM Albums
WHERE SEARCH(Title_Tokens, @p1) OR 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 respectivement liés à "fifth symphony" et "blue note".
SELECT albumid
FROM albums
WHERE spanner.search(title_tokens, $1) OR 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 avec(1 + @freshnessweight * GREATEST(0, 30 - DaysOld) / 30) - Popularité (
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) OR 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) OR 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, le cas échéant.
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é à "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
Booster les correspondances d'ordre des requêtes
Spanner applique un boost multiplicatif au résultat de la fonction SCORE pour les valeurs qui contiennent les termes de la requête dans le même ordre que celui dans lequel ils apparaissent dans la requête. Il existe deux versions de ce boost : correspondance partielle et correspondance exacte. Un boost de correspondance partielle est appliqué lorsque :
TOKENLISTcontient tous les termes d'origine de la requête.- Les jetons sont adjacents les uns aux autres et dans le même ordre que celui dans lequel 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 avec une négation ne peut pas recevoir de boost de correspondance partielle.
- Une requête avec une conjonction reçoit un boost si une partie de la conjonction apparaît aux emplacements appropriés.
- Une requête avec une expression reçoit un boost si l'expression apparaît dans le
TOKENLIST, si le terme à gauche de l'expression dans la requête apparaît à gauche de l'expression dans leTOKENLIST, et si le terme à droite de l'expression dans la requête apparaît à droite de l'expression dans le.
Spanner applique un boost de correspondance exacte lorsque toutes les règles précédentes sont vraies, et que les premier et dernier jetons de la requête sont les premier et dernier jetons du document.
Exemple de document : Bridge Over Troubled Water
| Requête | Boost appliqué |
|---|---|
| Pont en difficulté | pas de boost |
| Pont au-dessus d'une autre étendue d'eau | pas de boost |
| Bridge (Over OR Troubled) Water | pas de boost |
| Pont | boost partiel |
| Bridge Over (Troubled OR Water) | boost partiel |
| Bridge Over Troubled Water | boost exact |
| Bridge "Over Troubled" Water | boost exact |
| Bridge ("Over Troubled" OR missingterm) Water | boost exact |
Versions de l'outil de notation
L'algorithme de notation est mis à jour régulièrement. Chaque version regroupe un ensemble d'améliorations de l'algorithme de notation. Pour obtenir une liste détaillée des différences entre les versions, consultez Versions de l'outil d'évaluation.
Vous pouvez définir la version du scoreur par défaut pour votre base de données ou spécifier une version pour une requête spécifique.
Les bases de données créées après avril 2026 utiliseront par défaut la version 2 du scoreur. Les bases de données créées avant avril 2026 utilisent par défaut la version 1 jusqu'à ce que Spanner les migre vers la dernière version. Les bases de données créées en avril 2026, pendant le déploiement de la version 2, peuvent utiliser l'une ou l'autre version.
Si vous ne spécifiez pas de version de scorer pour votre base de données ou votre requête, la version par défaut du scorer est automatiquement mise à jour lorsqu'une version ultérieure est publiée.
Si vous paginez les résultats de recherche classés, les modifications de la version du scoreur peuvent entraîner l'omission ou la répétition de lignes sur les pages. Pour en savoir plus, consultez Paginer les résultats de recherche classés.
Définir la version par défaut du scoreur de la base de données
Vous pouvez définir la version par défaut de l'algorithme de notation pour votre base de données. Cette option détermine la version de l'algorithme de notation que Spanner utilise lorsque la fonction SCORE est appelée sans option de score version explicite.
GoogleSQL
Définissez l'option de base de données score_version :
ALTER DATABASE database_name SET OPTIONS (score_version = 2)
PostgreSQL
Définissez l'option de base de données spanner.score_version :
ALTER DATABASE database_name SET "spanner.score_version" = 2
Les valeurs valides pour l'option de base de données sont 1 ou 2. Si le paramètre version est présent dans une requête, il remplace la version par défaut de la base de données.
Remplacer la version du scorer par requête
Vous pouvez remplacer la version de l'outil de notation par défaut pour une requête spécifique à l'aide du paramètre version dans l'argument options de la fonction SCORE. Si une requête définit une version de l'outil de notation, elle remplace la version par défaut de la base de données.
L'exemple suivant remplace la version par défaut de l'outil de notation en spécifiant version dans le paramètre options :
GoogleSQL
SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, @query)
ORDER BY SCORE(
AlbumTitle_Tokens,
@query,
options=>JSON '{"version": 2}'
) DESC
PostgreSQL
Cet exemple utilise le paramètre de requête $1, qui est lié à la chaîne de requête.
SELECT albumid
FROM albums
WHERE spanner.search(albumtitle_tokens, $1)
ORDER BY spanner.score(
albumtitle_tokens,
$1,
options => '{"version": 2}'::jsonb
) DESC
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 n'est pas pratique de classer tous les résultats. Les requêtes de notation ont généralement deux limites :
- Limite de profondeur de récupération : nombre maximal de lignes à évaluer.
- Limite de taille de l'ensemble 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 avec des sous-requêtes SQL :
GoogleSQL
SELECT AlbumId
FROM
(
SELECT AlbumId, SCORE(Title_Tokens, @p1) AS score
FROM Albums
WHERE SEARCH(Title_Tokens, @p1)
ORDER BY ReleaseTimestamp DESC
LIMIT @retrieval_limit
)
ORDER BY score DESC
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 albumid
FROM
(
SELECT albumid, spanner.score(title_tokens, $1) AS score
FROM albums
WHERE spanner.search(title_tokens, $1)
ORDER BY releasetimestamp DESC
LIMIT $2
) AS subquery
ORDER BY score DESC
LIMIT $3
Cette approche est particulièrement efficace si Spanner utilise le signal de classement le plus important pour trier l'index.
Étapes suivantes
- 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 de texte intégral et des requêtes non textuelles.
- Découvrez comment effectuer une recherche dans plusieurs colonnes.