En esta página se describe la función SEARCH
y el modo de consulta mejorado, que se usan para realizar consultas de búsqueda de texto completo en tablas de Spanner.
Consultar un índice de búsqueda
Spanner proporciona la función SEARCH
para usarla en las consultas de índice de búsqueda. Un ejemplo de caso práctico sería una aplicación en la que los usuarios introducen texto en un cuadro de búsqueda y la aplicación envía la entrada del usuario directamente a la función SEARCH
. La función SEARCH
usaría un índice de búsqueda para encontrar ese texto.
La función SEARCH
requiere dos argumentos:
- Nombre de un índice de búsqueda
- Una consulta de búsqueda
La función SEARCH
solo funciona cuando se define un índice de búsqueda. La función SEARCH
se puede combinar con cualquier estructura SQL arbitraria, como filtros,
agregaciones o combinaciones.
La función SEARCH
no se puede usar con consultas de transacciones.
La siguiente consulta usa la función SEARCH
para devolver todos los álbumes que tengan friday
o monday
en el título:
GoogleSQL
SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, 'friday OR monday')
PostgreSQL
En este ejemplo se usa spanner.search.
SELECT albumid
FROM albums
WHERE spanner.search(albumtitle_tokens, 'friday OR monday')
Consulta de búsqueda
Las consultas de búsqueda usan la sintaxis de consulta de búsqueda sin procesar de forma predeterminada. Se pueden especificar sintaxis alternativas con el argumento SEARCH
dialect
.
Dialecto rquery
El dialecto predeterminado es consulta de búsqueda sin formato. Spanner usa un lenguaje específico de dominio (DSL) llamado rquery.
El lenguaje de rquery sigue las mismas reglas que el tokenizador de texto sin formato al dividir la consulta de búsqueda de entrada en términos distintos. Esto incluye la segmentación de idiomas asiáticos.
Para obtener información sobre cómo usar rquery, consulta la sintaxis de rquery.
dialecto de las palabras
La palabra dialect es como rquery, pero más sencilla. No usa ningún operador especial. Por ejemplo, OR
se trata como un término de búsqueda en lugar de como un operador de disyunción. Las comillas dobles se tratan como signos de puntuación en lugar de como una búsqueda de frase y se ignoran.
Con la palabra dialecto, AND
se aplica implícitamente a todos los términos y es obligatorio durante la coincidencia. Sigue las mismas reglas que el tokenizador de texto sin formato
al dividir la consulta de búsqueda de entrada en términos.
Para obtener información sobre el uso del dialecto de palabras, consulta la sintaxis de palabras.
words_phrase dialect
El dialecto words_phrase no usa ningún operador especial y todos los términos se tratan como una frase, lo que significa que los términos deben ser adyacentes y estar en el orden especificado.
Al igual que rquery, el dialecto words_phrase sigue las mismas reglas que el tokenizador de texto sin formato al dividir la consulta de búsqueda de entrada en términos.
Para obtener información sobre cómo usar el dialecto words_phrase, consulta la sintaxis de words_phrase.
Modo de consulta mejorado
Spanner ofrece dos modos de búsqueda de texto completo: una búsqueda básica basada en tokens y un modo más avanzado llamado enhance_query
. Si se habilita, la función
enhance_query
amplía la consulta de búsqueda para incluir términos relacionados y sinónimos,
lo que aumenta la probabilidad de encontrar resultados relevantes.
Para habilitar esta opción, asigna el argumento opcional enhance_query=>true
a la función SEARCH
. Por ejemplo, la consulta de búsqueda hotl cal
coincide con el álbum Hotel California
.
GoogleSQL
SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, 'hotl cal', enhance_query=>true)
PostgreSQL
SELECT albumid
FROM albums
WHERE spanner.search(albumtitle_tokens, 'hotl cal', enhance_query=>true)
El modo enhance_query
es una opción de tiempo de consulta. No afecta a la tokenización.
Puedes usar el mismo índice de búsqueda con o sin enhance_query
.
En Google, mejoramos continuamente los algoritmos de mejora de consultas. Por lo tanto, una consulta con enhance_query == true
podría dar resultados ligeramente diferentes con el tiempo.
Si el modo enhance_query
está habilitado, puede aumentar el número de términos que busca la función SEARCH
, lo que podría aumentar ligeramente la latencia.
Por ejemplo, la siguiente consulta usa un tiempo de espera de tres segundos y falla si enhance_query
no está disponible:
GoogleSQL
@{require_enhance_query=true, enhance_query_timeout_ms=3000}
SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, 'fast car', enhance_query=>true)
PostgreSQL
/*@require_enhance_query=true, enhance_query_timeout_ms=3000*/
SELECT albumid
FROM albums
WHERE spanner.search(albumtitle_tokens, 'fast car', enhance_query=>true)
Requisitos de las consultas de SQL
Una consulta de SQL debe cumplir varias condiciones para usar un índice de búsqueda. Si no se cumplen estas condiciones, la consulta usa un plan de consulta alternativo o falla si no existe ningún plan alternativo.
Las consultas deben cumplir las siguientes condiciones:
Las funciones BUSCAR y
SEARCH_SUBSTRING
requieren un índice de búsqueda. Spanner no admite estas funciones en consultas en la tabla base ni en los índices secundarios.Los índices particionados deben tener todas las columnas de partición enlazadas por una condición de igualdad en la cláusula
WHERE
de la consulta.Por ejemplo, si un índice de búsqueda se define como
PARTITION BY x, y
, la consulta debe tener una conjunción en la cláusulaWHERE
dex = <parameter or constant> AND y = <parameter or constant>
. El optimizador de consultas no tiene en cuenta ese índice de búsqueda si falta esa condición.Todas las columnas
TOKENLIST
a las que hacen referencia los operadoresSEARCH
ySEARCH_SUBSTRING
deben estar indexadas en el mismo índice de búsqueda.Por ejemplo, considere la siguiente tabla y definición de índice:
GoogleSQL
CREATE TABLE Albums ( AlbumId STRING(MAX) NOT NULL, AlbumTitle STRING(MAX), AlbumStudio STRING(MAX), AlbumTitle_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN, AlbumStudio_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumStudio)) HIDDEN ) PRIMARY KEY(AlbumId); CREATE SEARCH INDEX AlbumsTitleIndex ON Albums(AlbumTitle_Tokens); CREATE SEARCH INDEX AlbumsStudioIndex ON Albums(AlbumStudio_Tokens);
PostgreSQL
CREATE TABLE albums ( albumid character varying NOT NULL, albumtitle character varying, albumstudio character varying, albumtitle_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(albumtitle)) VIRTUAL HIDDEN, albumstudio_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(albumstudio)) VIRTUAL HIDDEN, PRIMARY KEY(albumid)); CREATE SEARCH INDEX albumstitleindex ON albums(albumtitle_tokens); CREATE SEARCH INDEX albumsstudioindex ON albums(albumstudio_tokens);
La siguiente consulta falla porque no hay ningún índice de búsqueda que indexe tanto
AlbumTitle_Tokens
comoAlbumStudio_Tokens
:GoogleSQL
SELECT AlbumId FROM Albums WHERE SEARCH(AlbumTitle_Tokens, @p1) AND SEARCH(AlbumStudio_Tokens, @p2)
PostgreSQL
En este ejemplo se usan los parámetros de consulta
$1
y$2
, que están vinculados a "fast car" y "blue note", respectivamente.SELECT albumid FROM albums WHERE spanner.search(albumtitle_tokens, $1) AND spanner.search(albumstudio_tokens, $2)
Si la columna de orden de clasificación admite valores nulos, tanto el esquema como la consulta deben excluir las filas en las que la columna de orden de clasificación sea NULL. Para obtener más información, consulta Orden de clasificación del índice de búsqueda.
Si el índice de búsqueda se filtra por NULL, la consulta debe incluir la misma expresión de filtrado por NULL que se usa en un índice. Consulta más información sobre las búsquedas con filtros NULL.
Los índices de búsqueda y las funciones de búsqueda no se admiten en DML, DML particionado ni consultas particionadas.
Los índices de búsqueda y las funciones de búsqueda se suelen usar en transacciones de solo lectura. Si los requisitos de la aplicación permiten que los resultados estén obsoletos, puede mejorar la latencia ejecutando consultas de búsqueda con una duración de obsolescencia de 10 segundos o más. Para obtener más información, consulta Leer datos obsoletos. Esto es especialmente útil para las consultas de búsqueda que se extienden a muchas divisiones de índice.
No se recomienda usar índices de búsqueda ni funciones de búsqueda en transacciones de lectura y escritura.
Durante la ejecución, las consultas de búsqueda bloquean una partición de índice completa. Por lo tanto, una tasa alta de consultas de búsqueda en transacciones de lectura y escritura puede provocar conflictos de bloqueo que deriven en picos de latencia. De forma predeterminada, los índices de búsqueda no se seleccionan automáticamente en las transacciones de lectura y escritura. Si se fuerza a una consulta a usar un índice de búsqueda en una transacción de lectura y escritura, se producirá un error de forma predeterminada. También falla si la consulta contiene alguna de las funciones de búsqueda. Este comportamiento se puede anular con la sugerencia a nivel de instrucción @{ALLOW_SEARCH_INDEXES_IN_TRANSACTION=TRUE}
de GoogleSQL (pero las consultas siguen siendo propensas a conflictos de bloqueo).
Una vez que se cumplen las condiciones de idoneidad del índice, el optimizador de consultas intenta acelerar las condiciones de consulta que no son de texto (como Rating > 4
). Si el índice de búsqueda no incluye la columna TOKENLIST
adecuada, la condición no se acelera y sigue siendo una condición residual.
Los parámetros de consulta
Los argumentos de consulta de búsqueda se especifican como un literal o un parámetro de consulta. Recomendamos usar parámetros de consulta para la búsqueda de texto completo en lugar de literales de cadena cuando los argumentos permitan el valor del parámetro de consulta.
Selección de índice
Spanner suele seleccionar el índice más eficiente para una consulta
mediante modelos basados en costes. Sin embargo, la sugerencia FORCE_INDEX
indica explícitamente a Spanner que use un índice de búsqueda específico. Por ejemplo, a continuación se muestra cómo obligar a Spanner a usar AlbumsIndex
:
GoogleSQL
SELECT AlbumId
FROM Albums @{FORCE_INDEX=AlbumsIndex}
WHERE SEARCH(AlbumTitle_Tokens, "fifth symphony")
PostgreSQL
SELECT albumid
FROM albums/*@force_index=albumsindex*/
WHERE spanner.search(albumtitle_tokens, 'fifth symphony')
Si el índice de búsqueda especificado no es válido, la consulta falla, aunque haya otros índices de búsqueda válidos.
Fragmentos en los resultados de búsqueda
Un fragmento es un texto extraído de una cadena determinada que ofrece a los usuarios una idea del contenido de un resultado de búsqueda y del motivo por el que el resultado es relevante para su consulta.
Por ejemplo, Gmail usa fragmentos para indicar la parte de un correo que coincide con la consulta de búsqueda:
Que la base de datos genere un fragmento tiene varias ventajas:
- Comodidad: no es necesario implementar lógica para generar fragmentos a partir de una consulta de búsqueda.
- Eficiencia: los fragmentos reducen el tamaño de la salida del servidor.
La función SNIPPET
crea el fragmento. Devuelve la parte pertinente del valor de cadena original junto con las posiciones de los caracteres que se deben destacar. El cliente puede elegir cómo mostrar el fragmento al usuario final (por ejemplo, usando texto destacado o en negrita).
Por ejemplo, en el siguiente ejemplo se usa SNIPPET
para obtener texto de AlbumTitle
:
GoogleSQL
SELECT AlbumId, SNIPPET(AlbumTitle, "Fast Car")
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, "Fast Car")
PostgreSQL
En este ejemplo se usa spanner.snippet.
SELECT albumid, spanner.snippet(albumtitle, 'Fast Car')
FROM albums
WHERE spanner.search(albumtitle_tokens, 'Fast Car')
Siguientes pasos
- Consulta cómo clasificar los resultados de búsqueda.
- Consulte cómo realizar una búsqueda de subcadenas.
- Consulta cómo paginar los resultados de búsqueda.
- Consulta cómo combinar consultas de texto completo y consultas que no son de texto.
- Consulta cómo buscar en varias columnas.