Trouver des correspondances proches avec la recherche proche

<ph type="x-smartling-placeholder">

Cette page explique comment utiliser une recherche proche dans le cadre d'une recherche dans le texte complet.

En plus d'effectuer des recherches de jetons exactes à l'aide des fonctions SEARCH et SEARCH_SUBSTRING, Spanner prend également en charge les recherches approximatives (ou floues). Les recherches floues permettent de trouver des documents correspondants malgré de légères différences entre la requête et le document.

Spanner accepte les types de recherche partielle suivants:

  • Recherche approximative basée sur les n-grammes
  • Recherche phonétique à l'aide de Soundex

La recherche floue basée sur les N-grammes repose sur la même tokenisation de sous-chaîne recherche de sous-chaîne requiert. La configuration de la fonction de tokenisation est importante, car elle affecte la qualité et les performances de la recherche. L'exemple suivant montre comment créer une requête avec des mots mal orthographiés ou orthographiés différemment pour trouver des correspondances approximatives dans l'index de recherche.

Schéma

CREATE TABLE Albums (
  AlbumId STRING(MAX) NOT NULL,
  AlbumTitle STRING(MAX),
  AlbumTitle_Tokens TOKENLIST AS (
    TOKENIZE_SUBSTRING(AlbumTitle, ngram_size_min=>2, ngram_size_max=>3,
                       relative_search_types=>["word_prefix", "word_suffix"])) HIDDEN
) PRIMARY KEY(AlbumId);

CREATE SEARCH INDEX AlbumsIndex
ON Albums(AlbumTitle_Tokens)
STORING (AlbumTitle);

Requête

La requête suivante recherche les albums dont les titres sont les plus proches de "Hatel Kaliphorn", comme "Hotel California".

SELECT AlbumId
FROM Albums
WHERE SEARCH_NGRAMS(AlbumTitle_Tokens, "Hatel Kaliphorn")
ORDER BY SCORE_NGRAMS(AlbumTitle_Tokens, "Hatel Kaliphorn") DESC
LIMIT 10

Optimiser les performances et la capacité de rappel pour une recherche approximative basée sur des n-grammes

L'exemple de requête de la section précédente effectue une recherche en deux phases, à l'aide de deux différentes fonctions:

  1. SEARCH_NGRAMS recherche tous les albums candidats qui ont partagé des n-grammes avec la requête de recherche. Par exemple, des n-grammes à trois caractères pour "Californie" inclure [cal, ali, lif, ifo, for, orn, rni, nia] et pour "Kaliphorn" inclure [kal, ali, lip, iph, pho, hor, orn]. Les N-grammes partagés dans ces ensembles de données sont [ali, orn]. Par défaut, SEARCH_NGRAMS fait correspondre tous les documents avec au moins deux n-grammes partagés. Par conséquent, "Kaliphorn" correspond à "Californie".
  2. SCORE_NGRAMS classe les correspondances par similarité. La similarité entre deux chaînes est définie comme Ratio entre les N-grammes partagés distincts et les N-grammes distincts non partagés:
$$ \frac{shared\_ngrams}{total\_ngrams_{index} + total\_ngrams_{query} - shared\_ngrams} $$

Habituellement, la requête search_query est la même dans SEARCH_NGRAMS et SCORE_NGRAMS .

Pour ce faire, nous vous recommandons d'utiliser l'argument avec des paramètres de requête plutôt que des littéraux de chaîne, et de spécifier le même paramètre de requête dans les fonctions SEARCH_NGRAMS et SCORE_NGRAMS.

Spanner comporte trois arguments de configuration que vous pouvez utiliser SEARCH_NGRAMS:

  1. Les tailles minimale et maximale des n-grammes spécifiés dans TOKENIZE_SUBSTRING ou TOKENIZE_NGRAMS. Nous vous déconseillons d'utiliser des n-grammes à un seul caractère, car ils correspondent à un très grand nombre de documents. En revanche, les n-grammes longs font que SEARCH_NGRAMS ne détecte pas les mots courts mal orthographiés.
  2. Nombre minimal d'n-grammes que SEARCH_NGRAMS doit faire correspondre (défini avec les arguments min_ngrams et min_ngrams_percent dans SEARCH_NGRAMS). Des valeurs plus élevées accélèrent généralement la requête, mais réduisent le rappel.

Pour obtenir un bon équilibre entre performances et rappel, ces arguments peuvent être configurés pour s'adapter à la requête et à la charge de travail spécifiques.

Nous vous recommandons également d'inclure un LIMIT interne pour éviter de créer lorsqu'une combinaison de n-grammes courants est détectée:

SELECT AlbumId
FROM (
  SELECT AlbumId,
         SCORE_NGRAMS(AlbumTitle_Tokens, @p) AS score
  FROM Albums
  WHERE SEARCH_NGRAMS(AlbumTitle_Tokens, @p)
  LIMIT 10000  # inner limit
)
ORDER BY score DESC
LIMIT 10  # outer limit

Recherche floue basée sur les n-grammes par rapport au mode de requête amélioré

En plus de la recherche floue basée sur les n-grammes, le mode de requête amélioré gère également certains mots mal orthographiés. Il existe donc un chevauchement entre les deux fonctionnalités. Le tableau suivant récapitule ces différences:

Recherche partielle basée sur les n-grammes Mode de requête amélioré
Coût Nécessite une tokenisation des sous-chaînes plus onéreuse basée sur n-grams Nécessite une tokenisation du texte complet moins coûteuse
Types de requêtes de recherche Fonctionne bien avec les documents courts avec quelques mots, par exemple, le nom d'une personne, d'une ville ou d'un produit Fonctionne aussi bien avec des documents et des requêtes de recherche de n'importe quelle taille
Recherche de mots partiels Effectue une recherche de sous-chaîne qui autorise les fautes d'orthographe Ne prend en charge que la recherche de mots entiers (SEARCH_SUBSTRING n'est pas compatible avec l'argument enhance_query)
Mots mal orthographiés Prise en charge des mots mal orthographiés dans l'index ou la requête N'accepte que les mots mal orthographiés dans la requête
Corrections Recherche les correspondances mal orthographiées, même si celles-ci n'existent pas Il corrige les fautes d'orthographe pour des mots courants et courants.

Effectuer une recherche phonétique avec Soundex

Spanner fournit la fonction SOUNDEX pour trouver des mots dont l'orthographe est différente, mais dont la prononciation est identique. Pour Par exemple, SOUNDEX("steven"), SOUNDEX("stephen") et SOUNDEX("stefan") sont tous "s315", tandis que SOUNDEX("stella") est "s340". SOUNDEX est sensible à la casse et ne fonctionne que pour les alphabets latins.

La recherche phonétique avec SOUNDEX peut être implémentée avec une colonne générée et une comme dans l'exemple suivant:

CREATE TABLE Singers (
  SingerId INT64,
  AlbumTitle STRING(MAX),
  AlbumTitle_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN,
  Name STRING(MAX),
  NameSoundex STRING(MAX) AS (LOWER(SOUNDEX(Name))),
  NameSoundex_Tokens TOKENLIST AS (TOKEN(NameSoundex)) HIDDEN
) PRIMARY KEY(SingerId);

CREATE SEARCH INDEX SingersPhoneticIndex ON Singers(AlbumTitle_Tokens, NameSoundex_Tokens);

La requête suivante fait correspondre "stefan" à "Steven" sur SOUNDEX, avec AlbumTitle contenant "cat" :

SELECT SingerId
FROM Singers
WHERE NameSoundex = LOWER(SOUNDEX("stefan")) AND SEARCH(AlbumTitle_Tokens, "cat")

Étape suivante