En esta página, se describe cómo concatenar TOKENLIST
en un índice de búsqueda cuando configuras tu esquema o en una búsqueda cuando realizas una búsqueda en el texto completo en Spanner.
Combina TOKENLIST en un índice de búsqueda
A veces, necesitas que tu aplicación realice búsquedas en campos individuales. En otras ocasiones, la aplicación debe realizar la búsqueda en todos los campos. Por ejemplo, en una tabla con dos columnas de cadena, es posible que desees que tu aplicación realice la búsqueda en ambas columnas sin diferenciar de qué columna provienen las coincidencias.
En Spanner, hay dos maneras de hacerlo:
- Divide las palabras por separado y concatena los
TOKENLIST
resultantes (recomendado). - Concatena cadenas y tokeniza el resultado.
Con el segundo enfoque, hay dos problemas:
- Si deseas indexar
Title
oStudio
de forma individual, además de indexarlos en unTOKENLIST
combinado, el mismo texto se segmenta dos veces. Esto hace que las transacciones usen más recursos. - Una búsqueda de frase abarca ambos campos. Por ejemplo, si
@p
se establece en"Blue Note"
, coincide con una fila que contieneTitle
="Big Blue Note" yStudio
="Blue Note Studios".
El primer enfoque resuelve estos problemas porque una frase solo coincide con un campo y cada campo de cadena solo se analiza una vez si se indexan los TOKENLIST
individuales y combinados. Aunque cada campo de cadena solo se tokeniza una vez,
los TOKENLIST
resultantes se almacenan por separado en el índice.
Tokeniza las palabras por separado y concatena TOKENLIST
En el siguiente ejemplo, se tokeniza cada palabra y se usa TOKENLIST_CONCAT
para concatenar los TOKENLIST
:
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
PostgreSQL usa spanner.tokenlist_concat
para la concatenación. El 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);
Ten en cuenta que tokenlist_concat
no llama a title_tokens
ni a studio_tokens
, sino a spanner.tokenize_fulltext(title)
y a spanner.tokenize_fulltext(studio)
. Esto se debe a que PostgreSQL no admite hacer referencia a columnas generadas que se encuentran dentro de otras columnas generadas. spanner.tokenlist_concat
debe llamar a las funciones de tokenización y no hacer referencia a las columnas de la lista de tokens directamente.
La concatenación de TOKENLIST
también se puede implementar por completo en el lado de la consulta.
Para obtener más información, consulta Concatenación TOKENLIST
del lado de la consulta.
TOKENLIST_CONCAT
es compatible con las búsquedas de texto completo y de subcadena.
Spanner no te permite combinar tipos de tokenización, como
TOKENIZE_FULLTEXT
y TOKENIZE_SUBSTRING
, en la misma llamada a TOKENLIST_CONCAT
.
En GoogleSQL, la definición de las columnas de texto TOKENLIST
se puede cambiar en las columnas no almacenadas para agregar columnas adicionales. Esto es útil cuando quieres agregar una columna adicional a TOKENLIST_CONCAT
. Cambiar la expresión de la columna generada no reabastece las filas existentes en el índice.
Concatena cadenas y tokeniza el resultado
En el siguiente ejemplo, se concatenan cadenas y se tokeniza el 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);
Cadena TOKENLIST
del lado de la consulta
La desventaja de indexar el TOKENLIST
concatenado es que aumenta el costo de almacenamiento y escritura. Cada token ahora se almacena en el disco dos veces: una vez en una lista de publicaciones de su TOKENLIST
original y una vez en una lista de publicaciones del TOKENLIST
combinado. La concatenación del lado de la consulta de las columnas TOKENLIST
evita este costo, pero la consulta usa más recursos de procesamiento.
Para concatenar varias TOKENLIST
, usa la función TOKENLIST_CONCAT
en la consulta SEARCH
. En esta sección, usaremos el siguiente esquema de muestra:
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);
La siguiente consulta busca filas que tengan los tokens "blue" y "note" en cualquier parte de las columnas Title
y Studio
. Esto incluye filas con "blue" y "note" en la columna Title
, "blue" y "note" en la columna Studio
, "blue" en la columna Title
y "note" en la columna Studio
, o lo opuesto.
GoogleSQL
SELECT AlbumId
FROM Albums
WHERE SEARCH(TOKENLIST_CONCAT([AlbumTitle_Tokens, Studio_Tokens]), 'blue note')
PostgreSQL
En este ejemplo, se usa spanner.search
con spanner.tokenlist_concat
.
SELECT albumid
FROM albums
WHERE spanner.search(spanner.tokenlist_concat(ARRAY[albumtitle_tokens, studio_tokens]), 'blue note')
La concatenación de TOKENLIST
del lado de la escritura y del lado de la consulta produce resultados idénticos.
La elección entre ambos es una compensación entre el costo del disco y el costo de la consulta.
Como alternativa, una aplicación podría buscar varias columnas TOKENLIST
y usar OR
junto con la función 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')
Sin embargo, esto tiene una semántica diferente. No coincide con los álbumes en los que AlbumTitle_Tokens
tiene “azul”, pero no “nota”, y Studio_Tokens
tiene “nota”, pero no “azul”.
¿Qué sigue?
- Obtén más información sobre las consultas de búsqueda de texto completo.
- Obtén información sobre los índices de búsqueda.