Cette page décrit la fonction SEARCH
et le mode de requête amélioré, qui sont
permettant d'effectuer une recherche en texte intégral
sur les tables Spanner.
Interroger un index de recherche
Spanner fournit
SEARCH
pour les requêtes d'index de recherche. La fonction SEARCH
nécessite deux arguments:
- Un nom dans l'index de recherche
- Une requête rquery
La fonction SEARCH
ne fonctionne que lorsqu'un index de recherche est défini. SEARCH
peut être combinée à n'importe quelle construction SQL arbitraire, telle que des filtres,
des agrégations ou des jointures.
La requête suivante utilise la fonction SEARCH
pour renvoyer tous les albums dont le contenu
friday
ou monday
dans le titre:
SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, 'friday OR monday')
Le langage rquery
Le deuxième argument de la fonction SEARCH
est un langage spécifique au domaine (DSL)
appelée rquery. Le langage rquery est similaire à celui des internautes
avez l'habitude d'utiliser sur google.com:
- L'utilisation de plusieurs termes implique
AND
. Par exemple, "Big Time" équivaut àbig AND time
. L'opération
OR
implique une disjonction entre deux termes, tels quebig OR time
. L'instructionSEARCH(tl, 'big time OR fast car')
équivaut à:SEARCH(tl, 'big') AND (SEARCH(tl, 'time') OR SEARCH(tl, 'fast')) AND SEARCH(tl, 'cat');
OR
ne s'applique qu'aux deux conditions adjacentes. Par exemple, la recherche l'expressionhappy friday OR monday
recherche tous les documents dont le contenu le termehappy
, et soit le termefriday
, soit le termemonday
.Les guillemets doubles correspondent à une recherche d'expression exacte. Par exemple, le rquery
"big cat"
correspond à "I have a big cat", mais pas à "My cat is big".L'opérateur
AROUND
fait correspondre les termes qui se trouvent à une certaine distance les uns des autres. Par exemple, la requêtebig AROUND cat
correspond à "big, white et duveteux", mais ne correspond pas à "gros chien était assis à côté d'un petit chat". Par défaut, les recherches s'appliquent aux termes séparés par cinq positions au maximum. À pour ajuster la distance, transmettez un argument à l'opérateurAROUND
. Spanner accepte deux syntaxes pourAROUND
:big AROUND(10) cat
big AROUND 10 cat
L'opérateur
AROUND
, lorsqu'il est utilisé dans une expression, peut faire correspondre des termes situés à une certaine distance les uns des autres et dans le même ordre (cinq jetons par défaut). Par exemple, la chaînebig AROUND cat
correspond "grand chat blanc et duveteux", mais pas "chat était grand".La négation d'un seul jeton est exprimée par un tiret (
-
). Exemple :-dog
correspond à tous les documents qui ne contiennent pas le termedog
.La ponctuation est généralement ignorée. Par exemple, "Big Time!" est équivalent à "Big Time".
La recherche n'est pas sensible à la casse. Par exemple, "Big Time" correspond à "big time".
Les opérateurs
The OR
etAROUND
sont sensibles à la casse. La barre verticale (|
) est un raccourci pourOR
.
Fonctionnement du langage rquery
Le langage rquery suit les mêmes règles que le outil de tokenisation en texte brut lors de la division de la chaîne d'entrée en termes distincts. Cela inclut la segmentation des langues asiatiques.
De nombreuses applications permettent aux utilisateurs de saisir une requête de recherche dans un
champ de recherche. Le moyen le plus simple d'intégrer ces requêtes d'utilisateurs finaux consiste à envoyer
l'entrée utilisateur directement dans la fonction SEARCH
.
Le tableau suivant explique la signification des différentes chaînes rquery:
rquery | Explication |
---|---|
Big Cat |
Fait correspondre les documents qui contiennent les deux termes "grand" et "chat". |
cat OR dog |
Correspond aux documents qui contiennent au moins l'un des termes "chat" et "chien". |
-cat |
Renvoie tous les documents qui ne contiennent pas le terme "chat". |
"big dog" -"big cat" |
Fait correspondre les documents qui contiennent deux termes adjacents "grand" et "chien", mais qui ne contiennent pas le mot "grand" à côté et "chat". Par exemple, cette requête correspond à "I have a big dog and a small cat", mais ne correspond pas à "I have a big dog and a small cat", mais ne renvoie pas à "I have a big dog and a small cat", un grand chien et un grand chat". |
cat|dog |
C'est la même chose que chat OR chien. |
and OR or |
Correspond aux documents contenant le terme "et" ou le terme « ou » (l'opérateur OR doit être en majuscules) |
Mode de requête amélioré
En plus de la recherche en texte intégral basée sur des jetons uniquement, Spanner
est compatible avec un mode plus riche appelé enhance_query
. Lorsqu'il est activé, ce mode étend
la requête de recherche pour inclure plus de variantes de jeton. Ces réécritures augmentent
rappel.
Pour activer cette option, définissez l'argument facultatif enhance_query=>true
dans
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'affecte pas la tokenisation.
Vous pouvez utiliser le même index de recherche avec ou sans enhance_query
.
Google améliore constamment ses algorithmes d'amélioration des requêtes. En tant que
résultat, une requête avec enhance_query == true
peut donner un résultat légèrement différent
résultats au fil du temps...
Lorsque le mode enhance_query
est activé, cela peut augmenter le nombre de termes
recherché par la fonction SEARCH
, ce qui peut entraîner une augmentation
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, 'cat', enhance_query=>true)
Exigences concernant les requêtes SQL
Une requête SQL doit remplir plusieurs conditions pour utiliser un index de recherche. Si ces conditions ne sont pas remplies, la requête utilise un autre plan de requête ou échoue s'il n'existe aucun autre forfait.
Les requêtes doivent remplir les conditions suivantes:
- Les fonctions
SEARCH
etSEARCH_SUBSTRING
nécessitent un index de recherche. Spanner n'accepte pas ces fonctions dans les requêtes sur la table de base ou les index secondaires. Requêtes sur Index partitionnés toutes les colonnes de partition doivent être liées par une condition d'égalité dans le
WHERE
de la requête.Par exemple, si un index de recherche est défini sur
PARTITION BY x, y
, le doit avoir un conjoint dans la clauseWHERE
dex = <parameter or constant> AND y = <parameter or constant>
. Cet index 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 parSEARCH
etSEARCH_SUBSTRING
doivent être indexés dans le même index de recherche.Prenons l'exemple de la définition de table et d'index suivante:
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 peut avoir une valeur nulle, le schéma et la requête doivent tous les deux exclure les lignes dont la colonne d'ordre de tri est NULL. Voir Ordre de tri de l'index de recherche pour en savoir plus.
Si l'index de recherche est filtré NULL, la requête doit inclure le même Expression de filtrage NULL utilisée dans un index. Voir une recherche filtrée par valeur NULL index pour en savoir plus.
Les index de recherche ne sont pas compatibles avec le LMD, le LMD partitionné et le LMD partitionné .
Les index de recherche sont généralement utilisés dans transactions en lecture seule. Si les exigences de l'application permettent d'obtenir des résultats obsolètes, nous vous recommandons d'exécuter des campagnes pour les requêtes dont la durée d'obsolescence est supérieure ou égale à 10 secondes. Pour plus pour en savoir plus, consultez Lire des données obsolètes : C'est particulièrement utile pour les requêtes de recherche volumineuses qui sont distribuées vers plusieurs Paxos groupes.
Les index de recherche ne sont pas recommandés dans transactions en lecture/écriture. Pendant l'exécution, les requêtes de recherche verrouillent l'intégralité d'une partition d'index. en tant que Résultat, un taux élevé de requêtes de recherche dans les transactions en lecture-écriture peut entraîner des conflits de verrouillage entraînant des pics de latence. Par défaut, les index de recherche automatiquement sélectionné dans les transactions en lecture/écriture. Si une requête est obligée de utilise un index de recherche dans une transaction en lecture-écriture, il échoue par défaut. Ce comportement peut être ignoré à l'aide de 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 les conditions d'éligibilité de l'index remplies, l'optimiseur de requête
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 demeure une condition résiduelle.
Paramètres de requête
rquery et d'autres paramètres tels que OFFSET
sont spécifiés sous la forme d'un littéral ou
Un paramètre de requête.
Nous vous recommandons d'utiliser des paramètres de requête plutôt que des littéraux de chaîne. Paramétrisé
les requêtes sont plus performantes
de succès de cache, ce qui entraîne
la latence des requêtes
et l'utilisation globale du processeur.
Par exemple, au lieu d'utiliser une requête comme celle-ci:
SELECT AlbumId FROM Albums WHERE SEARCH(AlbumTitle_Tokens, 'cat')
utilisez la syntaxe suivante:
SELECT AlbumId FROM Albums WHERE SEARCH(AlbumTitle_Tokens, @p)
Spanner exécute l'optimiseur de requêtes sur du texte SQL distinct. Moins textes SQL distincts utilisés par l'application, moins la requête l'optimisation est appelée.
Ordre de tri de l'index de recherche
Le comportement de l'ordre de tri des index de recherche est différent de celui des secondaires index.
Prenons l'exemple du tableau suivant:
CREATE TABLE Albums (
AlbumId STRING(MAX) NOT NULL,
ReleaseTimestamp INT64 NOT NULL,
AlbumName STRING(MAX),
AlbumName_Token TOKENLIST AS (TOKEN(AlbumName)) HIDDEN
) PRIMARY KEY(AlbumId);
L'application peut définir un index secondaire pour rechercher des informations à l'aide de la méthode
AlbumName
, trié par ReleaseTimestamp
:
CREATE INDEX AlbumsSecondaryIndex ON Albums(AlbumName, ReleaseTimestamp DESC);
L'index de recherche équivalent se présente comme suit (il utilise des mots clés exacts la tokenisation, car les index secondaires ne prennent pas en charge les recherches en texte intégral):
CREATE SEARCH INDEX AlbumsSearchIndex
ON Albums(AlbumName_Token)
ORDER BY ReleaseTimestamp DESC;
L'ordre de tri des index de recherche doit respecter les règles suivantes:
- N'utilisez des colonnes
INT64
que pour l'ordre de tri d'un indice de recherche. Les colonnes dont la taille est arbitraire en utilisent trop ressources dans l'index de recherche, car Spanner doit stocker le docid à côté de chaque jeton. Plus précisément, la colonne d'ordre de tri ne peut pas utiliser Le typeTIMESTAMP
, carTIMESTAMP
utilise une précision à la nanoseconde, ce qui ne tient pas dans un entier de 64 bits. Les colonnes d'ordre de tri ne doivent pas être
NULL
. Il existe deux façons d'y parvenir exigence:- Déclarez
NOT NULL
comme colonne d'ordre de tri. - Configurez l'index pour exclure les valeurs NULL.
- Déclarez
En pratique, un code temporel est souvent utilisé pour déterminer l'ordre de tri. Une approche est d'utiliser microsecondes puisque le système Unix epoch pour ces horodatages.
Les applications récupèrent généralement d'abord les données les plus récentes à l'aide d'un indice de recherche trié par ordre décroissant.
Sélection des 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. Cependant, la suggestion FORCE_INDEX
indique explicitement
Spanner pour utiliser un index de recherche spécifique. Par exemple,
ci-dessous montre comment forcer Spanner à utiliser AlbumsIndex
:
SELECT AlbumId
FROM Albums @{FORCE_INDEX=AlbumsIndex}
WHERE SEARCH(AlbumTitle_Tokens, @p1)
Si l'index de recherche spécifié n'est pas éligible, la propriété la requête échoue, même s'il existe d'autres index de recherche éligibles.
Extraits dans les résultats de recherche
Un extrait est un texte extrait d'une chaîne donnée qui donne aux utilisateurs une une idée du contenu d'un résultat de recherche et de la raison pour laquelle il est pertinentes par rapport à leur requête.
Gmail utilise par exemple des extraits pour indiquer la partie d'un e-mail qui correspond à la requête de recherche:
Le fait que la base de données génère un extrait présente plusieurs avantages:
- Commodité: vous n'avez pas besoin d'implémenter une logique pour générer des extraits. à partir d'une requête de recherche.
- Efficacité: les extraits de code réduisent la taille de la sortie du serveur.
La fonction SNIPPET
crée l'extrait. Elle renvoie la partie pertinente
la valeur de la chaîne d'origine ainsi que les positions
des caractères à mettre en surbrillance. La
le client peut ensuite choisir comment présenter l'extrait de code à 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, le code suivant 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 textuels.
- Découvrez comment effectuer une recherche dans plusieurs colonnes.