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 fuzzy). 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
Utilizzare una ricerca approssimativa basata su n-gram
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
GoogleSQL
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);
PostgreSQL
Questo esempio utilizza
spanner.tokenize_substring.
CREATE TABLE albums (
albumid character varying NOT NULL,
albumtitle character varying,
albumtitle_tokens spanner.tokenlist GENERATED ALWAYS AS (
spanner.tokenize_substring(albumtitle, ngram_size_min=>2, ngram_size_max=>3,
relative_search_types=>'{word_prefix, word_suffix}'::text[])) VIRTUAL HIDDEN,
PRIMARY KEY(albumid));
CREATE SEARCH INDEX albumsindex
ON albums(albumtitle_tokens)
INCLUDE (albumtitle);
Query
La seguente query trova gli album con titoli più simili a "Hatel Kaliphorn", ad esempio "Hotel California".
GoogleSQL
SELECT AlbumId
FROM Albums
WHERE SEARCH_NGRAMS(AlbumTitle_Tokens, "Hatel Kaliphorn")
ORDER BY SCORE_NGRAMS(AlbumTitle_Tokens, "Hatel Kaliphorn") DESC
LIMIT 10
PostgreSQL
Questi esempi utilizzano
spanner.score_ngrams
e
spanner.search_ngrams.
SELECT albumid
FROM albums
WHERE spanner.search_ngrams(albumtitle_tokens, 'Hatel Kaliphorn')
ORDER BY spanner.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:
SEARCH_NGRAMStrova tutti gli album candidati che hanno condiviso n-gram con la query di ricerca. Ad esempio, gli n-grammi di tre caratteri per "California" includono[cal, ali, lif, ifo, for, orn, rni, nia]e per "Kaliphorn" includono[kal, ali, lip, iph, pho, hor, orn]. Gli n-gram condivisi in questi set di dati sono[ali, orn]. Per impostazione predefinita,SEARCH_NGRAMScorrisponde a tutti i documenti con almeno due n-gram condivisi, pertanto "Kaliphorn" corrisponde a "California".SCORE_NGRAMSclassifica 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:
Di solito la query di ricerca è la stessa per le funzioni SEARCH_NGRAMS e
SCORE_NGRAMS. Il modo consigliato per farlo è utilizzare l'argomento con i parametri di query anziché con le stringhe letterali 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:
- Le dimensioni minime e massime per gli n-gram vengono specificate con le funzioni
TOKENIZE_SUBSTRING(/spanner/docs/reference/standard-sql/search_functions#tokenize_substring) oTOKENIZE_NGRAMS. Non consigliamo di utilizzare n-gram di un carattere perché potrebbero corrispondere a un numero molto elevato di documenti. D'altra parte, gli n-grammi lunghi fanno sì cheSEARCH_NGRAMSnon vengano rilevate parole brevi con errori ortografici. - Il numero minimo di n-gram che
SEARCH_NGRAMSdeve corrispondere (impostato con gli argomentimin_ngramsemin_ngrams_percentinSEARCH_NGRAMS). In genere, valori più elevati rendono la query più veloce, ma riducono il richiamo.
Per ottenere un buon equilibrio tra prestazioni e richiamo, puoi configurare questi argomenti 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.
GoogleSQL
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
PostgreSQL
Questo esempio utilizza il parametro di query $1 associato a "Hatel Kaliphorn".
SELECT albumid
FROM
(
SELECT albumid, spanner.score_ngrams(albumtitle_tokens, $1) AS score
FROM albums
WHERE spanner.search_ngrams(albumtitle_tokens, $1)
LIMIT 10000
) AS inner_query
ORDER BY inner_query.score DESC
LIMIT 10
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:
GoogleSQL
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);
PostgreSQL
Questo esempio utilizza
spanner.soundex.
CREATE TABLE singers (
singerid bigint,
albumtitle character varying,
albumtitle_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(albumtitle)) VIRTUAL HIDDEN,
name character varying,
namesoundex character varying GENERATED ALWAYS AS (lower(spanner.soundex(name))) VIRTUAL,
namesoundex_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.token(lower(spanner.soundex(name))) VIRTUAL 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":
GoogleSQL
SELECT SingerId
FROM Singers
WHERE NameSoundex = LOWER(SOUNDEX("stefan")) AND SEARCH(AlbumTitle_Tokens, "cat")
PostgreSQL
SELECT singerid
FROM singers
WHERE namesoundex = lower(spanner.soundex('stefan')) AND spanner.search(albumtitle_tokens, 'cat')
Passaggi successivi
- Scopri di più sulla tokenizzazione e sui tokenizzatori Spanner.
- Scopri di più sugli indici di ricerca.
- Scopri di più sulle query di ricerca a testo intero.