Esta página descreve como concatenar TOKENLIST
s num
índice de pesquisa quando configura o seu esquema
ou numa consulta de pesquisa quando faz uma pesquisa de texto integral no Spanner.
Combine TOKENLISTs num índice de pesquisa
Por vezes, precisa que a sua aplicação pesquise em campos individuais. Noutras ocasiões, a aplicação tem de pesquisar em todos os campos. Por exemplo, numa tabela com duas colunas de strings, pode querer que a sua aplicação pesquise em ambas as colunas sem distinguir a coluna de origem das correspondências.
No Spanner, existem duas formas de o fazer:
- Tokenize as palavras separadamente e concatene os
TOKENLIST
s resultantes (recomendado). - Concatenar strings e tokenizar o resultado.
Com a segunda abordagem, existem dois problemas:
- Se quiser indexar
Title
ouStudio
individualmente, além de os indexar numTOKENLIST
combinado, o mesmo texto é tokenizado duas vezes. Isto faz com que as transações usem mais recursos. - Uma pesquisa de expressão abrange ambos os campos. Por exemplo, se
@p
estiver definido como"Blue Note"
, corresponde a uma linha que contémTitle
="Big Blue Note" eStudio
="Blue Note Studios".
A primeira abordagem resolve estes problemas porque uma expressão só corresponde a um campo e cada campo de string só é tokenizado uma vez se os TOKENLIST
s individuais e combinados forem indexados. Embora cada campo de string seja tokenizado apenas uma vez, os TOKENLIST
resultantes são armazenados separadamente no índice.
Tokenize palavras separadamente e concatene TOKENLIST
s
O exemplo seguinte tokeniza cada palavra e usa
TOKENLIST_CONCAT
para concatenar os TOKENLIST
s:
GoogleSQL
CREATE TABLE Albums (
AlbumId STRING(MAX) NOT NULL,
Title STRING(MAX),
Studio STRING(MAX),
Title_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(Title)) HIDDEN,
Studio_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(Studio)) HIDDEN,
Combined_Tokens TOKENLIST AS (TOKENLIST_CONCAT([Title_Tokens, Studio_Tokens])) HIDDEN,
) PRIMARY KEY(AlbumId);
CREATE SEARCH INDEX AlbumsIndex ON Albums(Combined_Tokens);
SELECT AlbumId FROM Albums WHERE SEARCH(Combined_Tokens, @p);
PostgreSQL
O PostgreSQL usa
spanner.tokenlist_concat
para a concatenação. O parâmetro de consulta $1
está associado a "Hatel Kaliphorn".
CREATE TABLE albums (
albumid character varying NOT NULL,
title character varying,
studio character varying,
title_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(title)) VIRTUAL HIDDEN,
studio_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(studio)) VIRTUAL HIDDEN,
combined_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenlist_concat(ARRAY[spanner.tokenize_fulltext(title), spanner.tokenize_fulltext(studio)])) VIRTUAL HIDDEN,
PRIMARY KEY(albumid));
CREATE SEARCH INDEX albumsindex ON albums(combined_tokens);
SELECT albumid FROM albums WHERE spanner.search(combined_tokens, $1);
Tenha em atenção que tokenlist_concat
não chama title_tokens
nem studio_tokens
, mas chama spanner.tokenize_fulltext(title)
e spanner.tokenize_fulltext(studio)
. Isto deve-se ao facto de o PostgreSQL não suportar referências a colunas geradas que estejam dentro de outras colunas geradas. spanner.tokenlist_concat
tem de chamar funções de tokenização e não fazer referência diretamente a colunas de listas de tokens.
A concatenação TOKENLIST
também pode ser implementada totalmente no lado da consulta.
Para mais informações, consulte o artigo Concatenação TOKENLIST
no lado da consulta.
TOKENLIST_CONCAT
é suportado para pesquisas de texto completo e de subcadeias de carateres.
O Spanner não permite misturar tipos de tokenização, como TOKENIZE_FULLTEXT
e TOKENIZE_SUBSTRING
na mesma chamada TOKENLIST_CONCAT
.
No GoogleSQL, a definição das colunas de texto TOKENLIST
pode ser alterada em colunas não armazenadas para adicionar colunas adicionais. Isto é útil quando quer adicionar uma coluna adicional a TOKENLIST_CONCAT
. A alteração da expressão da coluna gerada não preenche as linhas existentes no índice.
Concatenar strings e tokenizar o resultado
O exemplo seguinte concatena strings e tokeniza o resultado:
GoogleSQL
CREATE TABLE Albums (
AlbumId STRING(MAX) NOT NULL,
Title STRING(MAX),
Studio STRING(MAX),
Combined_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(Title || " " || Studio)) HIDDEN,
) PRIMARY KEY(AlbumId);
CREATE SEARCH INDEX AlbumsIndex ON Albums(Combined_Tokens);
SELECT AlbumId FROM Albums WHERE SEARCH(Combined_Tokens, @p);
PostgreSQL
CREATE TABLE albums (
albumid character varying NOT NULL,
title character varying,
studio character varying,
combined_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(title || ' ' || studio)) VIRTUAL HIDDEN,
PRIMARY KEY(albumid));
CREATE SEARCH INDEX albumsindex ON albums(combined_tokens);
SELECT albumid FROM albums WHERE spanner.search(combined_tokens, $1);
Concatenação TOKENLIST
do lado da consulta
A contrapartida da indexação do TOKENLIST
concatenado é que aumenta o custo de armazenamento e gravação. Agora, cada token é armazenado no disco duas vezes:
uma vez numa lista de publicações do respetivo TOKENLIST
original e uma vez numa lista de publicações
do TOKENLIST
combinado. A concatenação do lado da consulta de colunas TOKENLIST
evita este custo, mas a consulta usa mais recursos de computação.
Para concatenar vários TOKENLIST
s, use a função
TOKENLIST_CONCAT
na consulta
SEARCH
. Para esta secção, estamos a usar o seguinte esquema de exemplo:
GoogleSQL
CREATE TABLE Albums (
AlbumId STRING(MAX) NOT NULL,
Title STRING(MAX),
Studio STRING(MAX),
Title_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(Title)) HIDDEN,
Studio_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(Studio)) HIDDEN,
) PRIMARY KEY(AlbumId);
CREATE SEARCH INDEX AlbumsIndex ON Albums(Title_Tokens, Studio_Tokens);
PostgreSQL
CREATE TABLE albums (
albumid character varying NOT NULL,
title character varying,
studio character varying,
title_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(title)) VIRTUAL HIDDEN,
studio_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(studio)) VIRTUAL HIDDEN,
PRIMARY KEY(albumid));
CREATE SEARCH INDEX albumsindex ON albums(title_tokens, studio_tokens);
A seguinte consulta pesquisa linhas que tenham os tokens "blue" e "note" em qualquer parte das colunas Title
e Studio
. Isto inclui linhas com "azul" e "nota" na coluna Title
, "azul" e "nota" na coluna Studio
, e "azul" na coluna Title
e "nota" na coluna Studio
, ou o contrário.
GoogleSQL
SELECT AlbumId
FROM Albums
WHERE SEARCH(TOKENLIST_CONCAT([AlbumTitle_Tokens, Studio_Tokens]), 'blue note')
PostgreSQL
Este exemplo usa
spanner.search
com
spanner.tokenlist_concat
.
SELECT albumid
FROM albums
WHERE spanner.search(spanner.tokenlist_concat(ARRAY[albumtitle_tokens, studio_tokens]), 'blue note')
A concatenação do lado da gravação e do lado da consulta produz resultados idênticos.TOKENLIST
A escolha entre as duas opções é um equilíbrio entre o custo do disco e o custo da consulta.
Em alternativa, uma aplicação pode pesquisar várias colunas TOKENLIST
e usar OR
juntamente com a função SEARCH
:
GoogleSQL
SEARCH(AlbumTitle_Tokens, 'Blue Note') OR SEARCH(Studio_Tokens, 'Blue Note')
PostgreSQL
spanner.search(albumtitle_tokens, 'Blue Note') OR spanner.search(studio_tokens, 'Blue Note')
No entanto, tem uma semântica diferente. Não corresponde a álbuns em que
AlbumTitle_Tokens
tem "azul", mas não "nota", e Studio_Tokens
tem
"nota", mas não "azul".
O que se segue?
- Saiba mais sobre as consultas de pesquisa de texto integral.
- Saiba mais sobre os índices de pesquisa.