Cette page décrit la fonction SEARCH
et le mode de requête amélioré, qui sont utilisés pour effectuer des requêtes de recherche en texte intégral sur les tables Spanner.
Interroger un index de recherche
Spanner fournit la fonction SEARCH
à utiliser pour les requêtes d'index de recherche. Un exemple de cas d'utilisation est une application dans laquelle les utilisateurs saisissent du texte dans un champ de recherche et que l'application envoie la saisie utilisateur directement dans la fonction SEARCH
. La fonction SEARCH utiliserait ensuite un indice de recherche pour trouver ce texte.
La fonction SEARCH
nécessite deux arguments:
- Nom d'un index de recherche
- Une requête de recherche
La fonction SEARCH
ne fonctionne que lorsqu'un indice de recherche est défini. La fonction SEARCH
peut être combinée à n'importe quelle construction SQL arbitraire, telle que des filtres, des agrégations ou des jointures.
La fonction SEARCH
ne peut pas être utilisée avec des requêtes de transaction.
La requête suivante utilise la fonction SEARCH
pour renvoyer tous les albums dont le titre contient friday
ou monday
:
SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, 'friday OR monday')
Requête de recherche
La requête de recherche utilise la syntaxe de requête de recherche brute par défaut. Vous pouvez spécifier d'autres syntaxes à l'aide de l'argument dialect
.
Dialecte rquery
Le dialecte par défaut est requête de recherche brute. Spanner utilise un langage spécifique à un domaine (DSL, domain-specific language) appelé rquery.
Le langage rquery suit les mêmes règles que le tokenizeur de texte brut lors de la division de la requête de recherche d'entrée en termes distincts. Cela inclut la segmentation des langues asiatiques.
Pour en savoir plus sur l'utilisation de rquery, consultez la section Syntaxe rquery.
dialecte des mots
Le dialecte de mots est semblable à rquery, mais plus simple. Il n'utilise aucun opérateur spécial. Par exemple, OR
est traité comme un terme de recherche au lieu d'un opérateur de disjonction. Les guillemets doubles sont traités comme des signes de ponctuation plutôt que comme une recherche de phrase et sont ignorés.
Avec les mots dialecte, AND
est appliqué implicitement à tous les termes et est obligatoire lors de la mise en correspondance. Il suit les mêmes règles que le tokenizer de texte brut lors de la division de la requête de recherche saisie en termes.
Pour en savoir plus sur l'utilisation du dialecte des mots, consultez la section Syntaxe des mots.
dialecte words_phrase
Le dialecte words_phrase n'utilise aucun opérateur spécial et tous les termes sont traités comme une phrase. Cela signifie que les termes doivent être adjacents et dans l'ordre spécifié.
Comme rquery, le dialecte words_phrase suit les mêmes règles que le tokenizer en texte brut lors de la division de la requête de recherche en termes.
Pour en savoir plus sur l'utilisation du dialecte words_phrase, consultez la section Syntaxe des expressions words.
Mode Requête amélioré
Spanner propose deux modes de recherche en texte intégral: une recherche de base basée sur des jetons et un mode plus avancé appelé enhance_query
. Lorsque cette option est activée, enhance_query
étend la requête de recherche pour inclure des termes et des synonymes associés, ce qui augmente la probabilité de trouver des résultats pertinents.
Pour activer cette option, définissez l'argument facultatif enhance_query=>true
dans la fonction SEARCH
. Par exemple, la requête de recherche hotl cal
correspond à l'album Hotel California
.
SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, 'hotl cal', enhance_query=>true)
Le mode enhance_query
est une option au moment de la requête. Cela n'a aucune incidence sur la tokenisation.
Vous pouvez utiliser le même indice de recherche avec ou sans enhance_query
.
Google améliore constamment les algorithmes d'amélioration des requêtes. Par conséquent, une requête avec enhance_query == true
peut produire des résultats légèrement différents au fil du temps.
Lorsque le mode enhance_query
est activé, il peut augmenter le nombre de termes recherchés par la fonction SEARCH
, ce qui peut légèrement augmenter la latence.
Par exemple, la requête suivante utilise un délai avant expiration de trois secondes et échoue si enhance_query
n'est pas disponible:
@{require_enhance_query=true, enhance_query_timeout_ms=3000}
SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, 'fast car', enhance_query=>true)
Pour en savoir plus sur l'utilisation de l'option enhance_query
, consultez la fonction SEARCH.
Exigences concernant les requêtes SQL
Une requête SQL doit remplir plusieurs conditions pour utiliser un indice de recherche. Si ces conditions ne sont pas remplies, la requête utilise un autre plan de requête ou échoue si aucun autre plan n'existe.
Les requêtes doivent répondre aux conditions suivantes:
Les fonctions
SEARCH
etSEARCH_SUBSTRING
nécessitent un indice de recherche. Spanner n'est pas compatible avec ces fonctions dans les requêtes adressées à la table de base ou aux index secondaires.Pour les index partitionnés, toutes les colonnes de partition doivent être liées par une condition d'égalité dans la clause
WHERE
de la requête.Par exemple, si un indice de recherche est défini sur
PARTITION BY x, y
, la requête doit comporter un conjoncteur dans la clauseWHERE
dex = <parameter or constant> AND y = <parameter or constant>
. Cet indice de recherche n'est pas pris en compte par l'optimiseur de requêtes si une telle condition est manquante.Toutes les colonnes
TOKENLIST
référencées par les opérateursSEARCH
etSEARCH_SUBSTRING
doivent être indexées dans le même indice de recherche.Prenons l'exemple de la table et de la définition d'index suivantes:
CREATE TABLE Albums ( AlbumId STRING(MAX) NOT NULL, AlbumTitle STRING(MAX), AlbumStudio STRING(MAX), AlbumTitle_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN, AlbumStudio_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumStudio)) HIDDEN ) PRIMARY KEY(AlbumId); CREATE SEARCH INDEX AlbumsTitleIndex ON Albums(AlbumTitle_Tokens); CREATE SEARCH INDEX AlbumsStudioIndex ON Albums(AlbumStudio_Tokens);
La requête suivante échoue, car il n'existe pas d'index de recherche unique qui indexe à la fois
AlbumTitle_Tokens
etAlbumStudio_Tokens
:SELECT AlbumId FROM Albums WHERE SEARCH(AlbumTitle_Tokens, @p1) AND SEARCH(AlbumStudio_Tokens, @p2)
Si la colonne d'ordre de tri est nullable, le schéma et la requête doivent exclure les lignes où la colonne d'ordre de tri est NULL. Pour en savoir plus, consultez la section Ordre de tri de l'index de recherche.
Si l'index de recherche est filtré par NULL, la requête doit inclure la même expression de filtrage NULL que celle utilisée dans un index. Pour en savoir plus, consultez la section Index de recherche filtré par NULL.
Les index de recherche et les fonctions de recherche ne sont pas compatibles avec le langage LMD, le langage LMD partitionné ni les requêtes partitionnées.
Les index de recherche et les fonctions de recherche sont généralement utilisés dans les transactions en lecture seule. Si les exigences de l'application autorisent les résultats obsolètes, nous vous recommandons d'exécuter des requêtes de recherche avec une durée d'obsolescence d'au moins 10 secondes. Pour en savoir plus, consultez la section Lire des données obsolètes. Cela est particulièrement utile pour les requêtes de recherche volumineuses qui se propagent à plusieurs groupes Paxos.
Les index de recherche et les fonctions de recherche ne sont pas recommandés dans les transactions en lecture-écriture. Lors de l'exécution, les requêtes de recherche verrouillent une partition d'index entière. Par conséquent, un taux élevé de requêtes de recherche dans les transactions en lecture-écriture peut entraîner des conflits de verrouillage, ce qui entraîne des pics de latence. Par défaut, les index de recherche ne sont pas automatiquement sélectionnés dans les transactions en lecture-écriture. Si une requête est forcée à utiliser un indice de recherche dans une transaction en lecture-écriture, elle échoue par défaut. Elle échouera également si la requête contient l'une des fonctions de recherche. Ce comportement peut être remplacé par l'indice au niveau de l'instruction
@{ALLOW_SEARCH_INDEXES_IN_TRANSACTION=TRUE}
(mais les requêtes sont toujours sujettes à des conflits de verrouillage).
Une fois que les conditions d'éligibilité de l'index sont remplies, l'optimiseur de requêtes tente d'accélérer les conditions de requête non textuelles (comme Rating > 4
). Si l'index de recherche n'inclut pas la colonne TOKENLIST
appropriée, la condition n'est pas accélérée et reste une condition résiduelle.
Paramètres de requête
Les arguments de la requête de recherche sont spécifiés sous la forme d'un littéral ou d'un paramètre de requête. Nous vous recommandons d'utiliser des paramètres de requête pour la recherche dans le texte intégral plutôt que des chaînes littérales lorsque les arguments autorisent la valeur du paramètre de requête.
Sélection d'index
Spanner sélectionne généralement l'index le plus efficace pour une requête à l'aide de la modélisation basée sur les coûts. Toutefois, l'indice FORCE_INDEX
indique explicitement à Spanner d'utiliser un indice de recherche spécifique. Par exemple, l'exemple suivant montre comment forcer Spanner à utiliser AlbumsIndex
:
SELECT AlbumId
FROM Albums @{FORCE_INDEX=AlbumsIndex}
WHERE SEARCH(AlbumTitle_Tokens, "fifth symphony")
Si l'index de recherche spécifié n'est pas éligible, la requête échoue, même si d'autres index de recherche éligibles sont disponibles.
Extraits dans les résultats de recherche
Un extrait est un fragment de texte extrait d'une chaîne donnée qui donne aux utilisateurs une idée du contenu d'un résultat de recherche et de la raison pour laquelle il est pertinent par rapport à leur requête.
Par exemple, Gmail utilise des extraits pour indiquer la partie d'un e-mail qui correspond à la requête de recherche:
La génération d'un extrait par la base de données présente plusieurs avantages:
- Pratique: vous n'avez pas besoin d'implémenter de logique pour générer des extraits à partir d'une requête de recherche.
- Efficacité: les extraits réduisent la taille de sortie du serveur.
La fonction SNIPPET
crée l'extrait. Elle renvoie la partie pertinente de la valeur de la chaîne d'origine, ainsi que les positions des caractères à mettre en surbrillance. Le client peut ensuite choisir comment afficher l'extrait à l'utilisateur final (par exemple, en utilisant du texte en surbrillance ou en gras). La fonction SNIPPET
supprime toutes les balises HTML de la chaîne d'origine.
Par exemple, la commande suivante utilise SNIPPET
pour récupérer du texte à partir de AlbumTitle
:
SELECT AlbumId, SNIPPET(AlbumTitle, "Fast Car")
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, "Fast Car")
Étape suivante
- Découvrez comment classer les résultats de recherche.
- 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.