Trovare corrispondenze approssimative con la ricerca approssimativa

Questa pagina descrive come utilizzare una ricerca fuzzy nell'ambito di una ricerca a testo intero.

Oltre a eseguire ricerche di token esatti utilizzando le funzioni SEARCH e SEARCH_SUBSTRING, Spanner supporta anche le ricerche approssimative (o imprecise). Le ricerche approssimative trovano documenti corrispondenti nonostante piccole differenze tra la query e il documento.

Spanner supporta i seguenti tipi di ricerca approssimativa:

  • Ricerca approssimativa basata su n-gram
  • Ricerca fonetica utilizzando Soundex

La ricerca approssimativa basata su n-gram si basa sulla stessa tokenizzazione delle sottostringhe richiesta da una ricerca di sottostringhe. La configurazione dello tokenizer è importante perché influisce sulla qualità e sulle prestazioni della ricerca. L'esempio seguente mostra come creare una query con parole con errori ortografici o con ortografia diversa per trovare corrispondenze approssimative nell'indice di ricerca.

Schema

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);

Query

La seguente query trova gli album con titoli più simili a "Hatel Kaliphorn", ad esempio "Hotel California".

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

Ottimizzare il rendimento e il recupero per una ricerca approssimativa basata su n-gram

La query di esempio nella sezione precedente esegue ricerche in due fasi, utilizzando due funzioni diverse:

  1. SEARCH_NGRAMS trova tutti gli album candidati che hanno condiviso n-gram con la query di ricerca. Ad esempio, gli n-grammi di tre caratteri per "California" includeranno [cal, ali, lif, ifo, for, orn, rni, nia] e per "Kaliphorn" includeranno [kal, ali, lip, iph, pho, hor, orn]. Gli n-gram condivisi in questi set di dati sono [ali, orn]. Per impostazione predefinita, SEARCH_NGRAMS corrisponde a tutti documenti con almeno due n-gram condivisi, pertanto "Kaliphorn" corrisponde "California".
  2. SCORE_NGRAMS classifica le corrispondenze in base alla somiglianza. La somiglianza di due stringhe è definita come il rapporto tra n-grammi condivisi distinti e n-grammi non condivisi distinti:
$$ \frac{shared\_ngrams}{total\_ngrams_{index} + total\_ngrams_{query} - shared\_ngrams} $$

In genere, la query di ricerca è la stessa sia per la funzione SEARCH_NGRAMS sia per la funzione SCORE_NGRAMS. Il modo consigliato per farlo è utilizzare l'argomento con parametri di query anziché con una stringa letterale e specificare lo stesso parametro di query nelle funzioni SEARCH_NGRAMS e SCORE_NGRAMS.

Spanner ha tre argomenti di configurazione che possono essere utilizzati con SEARCH_NGRAMS:

  1. Le dimensioni minime e massime degli n-gram specificati in TOKENIZE_SUBSTRING o TOKENIZE_NGRAMS. Non consigliamo gli n-grammi di un carattere perché corrispondono a un numero molto elevato di documenti. D'altra parte, gli n-grammi lunghi fanno sì che SEARCH_NGRAMS smarriscano parole brevi con errori ortografici.
  2. Numero minimo di n-gram che SEARCH_NGRAMS deve corrispondere (impostato con gli argomenti min_ngrams e min_ngrams_percent in SEARCH_NGRAMS). In genere, numeri più elevati rendono la query più rapida, ma riducono il richiamo.

Per ottenere un buon equilibrio tra prestazioni e richiamo, questi argomenti possono essere configurati in base alla query e al carico di lavoro specifici.

Ti consigliamo inoltre di includere un LIMIT interno per evitare di creare query molto costose quando viene rilevata una combinazione di n-gram popolari:

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

Ricerca approssimativa basata su n-gram e modalità di query avanzata

Oltre alla ricerca approssimativa basata su n-gram, la modalità di query avanzata gestisce anche alcune parole con errori ortografici. Pertanto, esiste una certa sovrapposizione tra le due funzionalità. La seguente tabella riassume le differenze:

Ricerca approssimativa basata su n-gram Modalità di query avanzata
Costo Richiede una tokenizzazione di sottostringhe più costosa in base ai gruppi di n caratteri Richiede una tokenizzazione del testo completo meno costosa
Tipi di query di ricerca Funziona bene con documenti brevi contenenti poche parole, come il nome di una persona, di una città o di un prodotto Funzionano ugualmente bene con documenti e query di ricerca di qualsiasi dimensione
Ricerca di parole parziali Esegue una ricerca di sottostringhe che consente errori ortografici Supporta solo la ricerca di intere parole (SEARCH_SUBSTRING non supporta l'argomento enhance_query)
Parole con errori ortografici Supporta le parole con errori ortografici nell'indice o nella query Supporta solo le parole con errori ortografici nella query
Correzioni Trova eventuali corrispondenze con errori ortografici, anche se la corrispondenza non è una parola reale Corregge gli errori ortografici delle parole comuni e note

Eseguire una ricerca fonetica con Soundex

Spanner fornisce la funzione SOUNDEX per trovare parole scritte in modo diverso, ma che suonano allo stesso modo. Ad esempio, SOUNDEX("steven"), SOUNDEX("stephen") eSOUNDEX("stefan") sono tutti "s315", mentre SOUNDEX("stella") è "s340". SOUNDEX è sensibile alle maiuscole e funziona solo per gli alfabeti basati sul latino.

La ricerca fonetica con SOUNDEX può essere implementata con una colonna generata e un indice di ricerca, come mostrato nell'esempio seguente:

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 seguente query associa "stefan" a "Steven" in SOUNDEX, nonché AlbumTitle contenente "gatto":

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

Passaggi successivi