Esta página descreve como usar uma pesquisa aproximada como parte de uma pesquisa de texto completo.
Além de realizar pesquisas exatas de tokens com as funções
SEARCH
e
SEARCH_SUBSTRING
, o Spanner também suporta pesquisas aproximadas (ou difusas). As pesquisas aproximadas encontram documentos correspondentes apesar das pequenas diferenças entre a consulta e o documento.
O Spanner suporta os seguintes tipos de pesquisa aproximada:
- Pesquisa aproximada baseada em n-gramas
- Pesquisa fonética com o algoritmo Soundex
Use uma pesquisa aproximada baseada em n-gramas
A pesquisa aproximada baseada em n-gramas baseia-se na mesma tokenização de subcadeias que uma pesquisa de subcadeias requer. A configuração do tokenizador é importante, pois afeta a qualidade e o desempenho da pesquisa. O exemplo seguinte mostra como criar uma consulta com palavras com erros ortográficos ou escritas de forma diferente para encontrar correspondências aproximadas no índice de pesquisa.
Esquema
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
Este exemplo usa
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);
Consulta
A seguinte consulta encontra os álbuns com títulos mais próximos de "Hatel Kaliphorn", como "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
Estes exemplos usam
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
Otimize o desempenho e a capacidade de memorização para uma pesquisa aproximada baseada em n-gramas
A consulta de exemplo na secção anterior pesquisa em duas fases, usando duas funções diferentes:
SEARCH_NGRAMS
encontra todos os álbuns candidatos que têm n-gramas partilhados com a consulta de pesquisa. Por exemplo, os n-gramas de três carateres para "California" incluem[cal, ali, lif, ifo, for, orn, rni, nia]
e para "Kaliphorn" incluem[kal, ali, lip, iph, pho, hor, orn]
. Os n-gramas partilhados nestes conjuntos de dados são[ali, orn]
. Por predefinição,SEARCH_NGRAMS
corresponde a todos os documentos com, pelo menos, dois n-gramas partilhados. Por isso, "Kaliphorn" corresponde a "California".SCORE_NGRAMS
classifica as correspondências por semelhança. A semelhança de duas strings é definida como uma relação de n-gramas partilhados distintos com n-gramas não partilhados distintos:
Normalmente, a consulta de pesquisa é a mesma nas funções SEARCH_NGRAMS
e SCORE_NGRAMS
. A forma recomendada de o fazer é usar o argumento
com
parâmetros de consulta
em vez de literais de strings e especificar o mesmo parâmetro de consulta nas funções
SEARCH_NGRAMS
e SCORE_NGRAMS
.
O Spanner tem três argumentos de configuração que podem ser usados com
SEARCH_NGRAMS
:
- Os tamanhos mínimo e máximo dos n-gramas são especificados com as funções
TOKENIZE_SUBSTRING
(/spanner/docs/reference/standard-sql/search_functions#tokenize_substring) ouTOKENIZE_NGRAMS
. Não recomendamos n-gramas de um carater, porque podem corresponder a um número muito elevado de documentos. Por outro lado, os n-gramas longos fazem com que oSEARCH_NGRAMS
não detete palavras curtas com erros ortográficos. - O número mínimo de n-gramas que
SEARCH_NGRAMS
tem de corresponder (definido com os argumentosmin_ngrams
emin_ngrams_percent
emSEARCH_NGRAMS
). Os números mais elevados normalmente tornam a consulta mais rápida, mas reduzem a evocação.
Para alcançar um bom equilíbrio entre o desempenho e a capacidade de memorização, pode configurar estes argumentos para se adequarem à consulta e à carga de trabalho específicas.
Também recomendamos a inclusão de um LIMIT
interno para evitar a criação de consultas muito dispendiosas quando é encontrada uma combinação de n-gramas populares.
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
Este exemplo usa o parâmetro de consulta $1
, que está associado 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
Pesquisa aproximada baseada em n-gramas versus modo de consulta melhorado
Além da pesquisa aproximada baseada em n-gramas, o modo de consulta melhorado também processa algumas palavras com erros ortográficos. Assim, existe alguma sobreposição entre as duas funcionalidades. A tabela seguinte resume as diferenças:
Pesquisa aproximada baseada em n-gramas | Modo de consulta melhorado | |
Custo | Requer uma tokenização de subcadeias mais cara com base em n-gramas | Requer uma tokenização de texto completo menos dispendiosa |
Tipos de consultas de pesquisa | Funciona bem com documentos curtos com algumas palavras, como o nome de uma pessoa, o nome de uma cidade ou o nome de um produto | Funciona igualmente bem com documentos de qualquer tamanho e consultas de pesquisa de qualquer tamanho |
Pesquisa de palavras parciais | Executa uma pesquisa de subcadeias que permite erros ortográficos | Só suporta uma pesquisa de palavras inteiras (SEARCH_SUBSTRING
não suporta o argumento enhance_query )
|
Palavras com erros ortográficos | Suporta palavras com erros ortográficos no índice ou na consulta | Apenas suporta palavras com erros ortográficos na consulta |
Correções | Encontra quaisquer correspondências com erros ortográficos, mesmo que a correspondência não seja uma palavra real | Corrige erros ortográficos de palavras comuns e conhecidas |
Faça uma pesquisa fonética com o Soundex
O Spanner fornece a função
SOUNDEX
para encontrar palavras que são escritas de forma diferente, mas que têm o mesmo som. Por exemplo, SOUNDEX("steven")
, SOUNDEX("stephen")
e SOUNDEX("stefan")
são todos "s315", enquanto SOUNDEX("stella")
é "s340". SOUNDEX
é sensível a maiúsculas e minúsculas e só funciona para alfabetos baseados no latim.
A pesquisa fonética com SOUNDEX
pode ser implementada com uma coluna gerada e um índice de pesquisa, conforme mostrado no exemplo seguinte:
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
Este exemplo usa
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);
A seguinte consulta faz corresponder "stefan" a "Steven" em SOUNDEX
, juntamente com
AlbumTitle
que contenha "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')
O que se segue?
- Saiba mais sobre a conversão em tokens e os tokenizadores do Spanner.
- Saiba mais sobre os índices de pesquisa.
- Saiba mais sobre as consultas de pesquisa de texto integral.