Questa pagina descrive come utilizzare una ricerca approssimativa nell'ambito di una ricerca full-text.
Oltre a eseguire ricerche esatte di token utilizzando le funzioni
SEARCH
e
SEARCH_SUBSTRING, Spanner supporta anche le ricerche approssimative (o fuzzy). Le ricerche
approssimative trovano documenti corrispondenti nonostante le piccole differenze tra la query e
il documento.
Spanner supporta i seguenti tipi di ricerca fuzzy:
- Ricerca approssimativa basata su n-grammi
- Ricerca fonetica tramite Soundex
Utilizzare una ricerca approssimativa basata sugli n-grammi
La ricerca approssimativa basata su n-grammi si basa sulla stessa tokenizzazione delle sottostringhe richiesta dalla ricerca di sottostringhe. La configurazione del tokenizer è importante perché influisce sulla qualità e sul rendimento della ricerca. Il seguente esempio mostra come creare una query con parole con errori ortografici o scritte in modo diverso 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
Questo esempio utilizza
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 richiamo per una ricerca approssimativa basata su n-grammi
La query di esempio nella sezione precedente esegue la ricerca in due fasi, utilizzando due funzioni diverse:
SEARCH_NGRAMStrova tutti gli album candidati che hanno condiviso n-grammi con la query di ricerca. Ad esempio, i trigrammi per "California" includono[cal, ali, lif, ifo, for, orn, rni, nia]e per "Kaliphorn" includono[kal, ali, lip, iph, pho, hor, orn]. Gli n-grammi condivisi in questi set di dati sono[ali, orn]. Per impostazione predefinita,SEARCH_NGRAMScorrisponde a tutti i documenti con almeno due n-grammi condivisi, pertanto "Kaliphorn" corrisponde a "California".SCORE_NGRAMSclassifica le corrispondenze in base alla somiglianza. La somiglianza di due stringhe è definita come un rapporto tra n-grammi condivisi distinti e n-grammi non condivisi distinti:
Di solito, la query di ricerca è la stessa sia per le funzioni SEARCH_NGRAMS che per quelle SCORE_NGRAMS. Il modo consigliato per farlo è utilizzare l'argomento
con
i parametri di query
anziché con i valori letterali stringa 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-grammi sono specificate con le funzioni
TOKENIZE_SUBSTRINGoTOKENIZE_NGRAMS. Non consigliamo n-grammi di un solo carattere perché potrebbero corrispondere a un numero molto elevato di documenti. D'altra parte, gli n-grammi lunghiSEARCH_NGRAMSnon rilevano le parole brevi con errori ortografici. - Il numero minimo di n-grammi che
SEARCH_NGRAMSdeve corrispondere (impostato con gli argomentimin_ngramsemin_ngrams_percentinSEARCH_NGRAMS). I numeri più alti in genere 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.
Consigliamo inoltre di includere un LIMIT interno per evitare di creare query molto costose quando viene rilevata una combinazione di n-grammi 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
spanner.score_ngrams
e
spanner.search_ngrams.
Il parametro di ricerca $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-grammi e modalità query avanzata
Oltre alla ricerca approssimativa basata sugli n-grammi, 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-grammi | Modalità di query avanzata | |
| Costo | Richiede una tokenizzazione di sottostringhe più costosa basata su n-grammi | Richiede una tokenizzazione full-text meno costosa |
| Tipi di query di ricerca | Funziona bene con documenti brevi con poche parole, ad esempio con il nome di una persona, di una città o di un prodotto | Funziona altrettanto bene con documenti di qualsiasi dimensione 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 parole intere (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 errate nella query |
| Correzioni | Trova tutte le corrispondenze con errori ortografici, anche se la corrispondenza non è una parola reale | Corregge gli errori ortografici per le parole comuni e note |
Eseguire una ricerca fonetica con Soundex
Spanner fornisce la funzione
SOUNDEX
per trovare parole scritte in modo diverso, ma che hanno lo stesso suono. Ad esempio, SOUNDEX("steven"), SOUNDEX("stephen") eSOUNDEX("stefan") sono
tutti "s315", mentre SOUNDEX("stella") è "s340". SOUNDEX fa distinzione tra maiuscole e minuscole 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" su SOUNDEX, insieme a
AlbumTitle contenente "cat":
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 full-text.