Esta página descreve como concatenar TOKENLISTs em um
índice de pesquisa ao configurar o esquema
ou em uma consulta de pesquisa ao realizar uma pesquisa de texto completo no Spanner.
Combinar TOKENLISTs em um índice de pesquisa
Às vezes, o aplicativo precisa pesquisar em campos individuais. Em outras ocasiões, o aplicativo precisa pesquisar em todos os campos. Por exemplo, em uma tabela com duas colunas de string, talvez você queira que o aplicativo pesquise nas duas colunas sem diferenciar de qual coluna as correspondências vêm.
No Spanner, há duas maneiras de fazer isso:
- Tokenize palavras separadamente e concatene as
TOKENLISTs resultantes (recomendado). - Concatene strings e tokeniza o resultado.
Com a segunda abordagem, há dois problemas:
- Se você quiser indexar
TitleouStudioindividualmente, além de indexá-los em umaTOKENLISTcombinada, o mesmo texto será tokenizado duas vezes. Isso faz com que as transações usem mais recursos. - Uma pesquisa de frase abrange os dois campos. Por exemplo, se
@pestiver definido como"Blue Note", ele vai corresponder a uma linha que contémTitle="Big Blue Note" eStudio="Blue Note Studios".
A primeira abordagem resolve esses problemas porque uma frase só corresponde a um campo e cada campo de string só é tokenizado uma vez se as TOKENLISTs individuais e combinadas forem indexadas. Embora cada campo de string seja tokenizado apenas uma vez, as TOKENLISTs resultantes são armazenadas separadamente no índice.
Tokenizar palavras separadamente e concatenar TOKENLISTs
O exemplo a seguir tokeniza cada palavra e usa
TOKENLIST_CONCAT
para concatenar as TOKENLISTs:
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 concatenação. O parâmetro de consulta $1 está vinculado 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);
Observe que tokenlist_concat não chama title_tokens ou studio_tokens, mas chama spanner.tokenize_fulltext(title) e spanner.tokenize_fulltext(studio). Isso ocorre porque o PostgreSQL não oferece suporte à referência de colunas geradas que estão dentro de outras colunas geradas. spanner.tokenlist_concat precisa chamar funções de tokenização e não referenciar colunas de tokenlist diretamente.
A concatenação de TOKENLIST também pode ser implementada totalmente no lado da consulta.
Para mais informações, consulte Concatenação TOKENLIST
do lado da consulta.
TOKENLIST_CONCAT é compatível com pesquisas de texto completo e de
substring searches.
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 de colunas de TOKENLIST de texto pode ser alterada em colunas não armazenadas para adicionar outras colunas. Isso é útil quando você quer adicionar outra coluna a TOKENLIST_CONCAT. A alteração da expressão da coluna gerada não preenche as linhas atuais no índice.
Concatene strings e tokeniza o resultado
O exemplo a seguir 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 de TOKENLIST do lado da consulta
A desvantagem de indexar a TOKENLIST concatenada é que ela aumenta o custo de armazenamento e gravação. Cada token agora é armazenado no disco duas vezes: uma em uma lista de postagens da TOKENLIST original e outra em uma lista de postagens da TOKENLIST combinada. A concatenação de colunas TOKENLIST do lado da consulta evita esse custo, mas a consulta usa mais recursos de computação.
Para concatenar várias TOKENLISTs, use a
TOKENLIST_CONCAT
função na
SEARCH
consulta. Para esta seção, estamos usando o seguinte esquema de amostra:
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 consulta a seguir pesquisa linhas que têm os tokens "blue" e "note" em qualquer lugar nas colunas Title e Studio. Isso inclui linhas com "blue" e "note" na coluna Title, "blue" e "note" na coluna Studio e "blue" na coluna Title e "note" na coluna Studio, ou o oposto.
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 de TOKENLIST do lado da gravação e da consulta produz resultados idênticos.
A escolha entre os dois é uma compensação entre o custo do disco e o custo da consulta.
Como alternativa, um aplicativo pode pesquisar várias colunas TOKENLIST e usar OR 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, isso tem semântica diferente. Ele não corresponde a álbuns em que AlbumTitle_Tokens tem "blue", mas não "note" e Studio_Tokens tem "note", mas não "blue".
A seguir
- Saiba mais sobre consultas de pesquisa de texto completo.
- Saiba mais sobre índices de pesquisa.