En esta página, se describen 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 usar en las consultas de índices de búsqueda. Un ejemplo de caso de uso sería una aplicación en la que los usuarios ingresan texto en un cuadro de búsqueda y la aplicación envía la entrada del usuario directamente a la función SEARCH. Luego, la función SEARCH usaría un índice de búsqueda para encontrar ese texto.
La función SEARCH requiere dos argumentos:
- Nombre del índice de búsqueda
- Una 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 construcción de SQL arbitraria, como filtros, agregaciones o uniones.
La función SEARCH no se puede usar con consultas de transacción.
La siguiente consulta usa la función SEARCH para devolver todos los álbumes que tienen 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')
Búsqueda
De forma predeterminada, las búsquedas utilizan la sintaxis de búsqueda sin procesar. Se pueden especificar sintaxis alternativas con el argumento SEARCH
dialect.
Dialecto de rquery
El dialecto predeterminado es búsqueda sin procesar. Spanner usa un lenguaje específico del dominio (DSL) llamado rquery.
El lenguaje de rquery sigue las mismas reglas que el tokenizador de texto sin formato cuando divide 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 el uso de rquery, consulta Sintaxis de rquery.
dialecto de palabras
La palabra dialect es similar a rquery, pero más simple. No usa ningún operador especial. Por ejemplo, OR se trata como un término de búsqueda en lugar de un operador de disyunción. Las comillas dobles se manejan como signos de puntuación en lugar de una búsqueda de frases y se ignoran.
Con el dialecto de palabras, AND se aplica de forma implícita a todos los términos y se requiere durante la coincidencia. Sigue las mismas reglas que el tokenizador de texto sin formato cuando divide la búsqueda de entrada en términos.
Para obtener información sobre el uso del dialecto de palabras, consulta la sintaxis de palabras.
Dialecto de words_phrase
El dialecto words_phrase no usa operadores especiales 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 cuando divide la 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 en el texto completo: una búsqueda básica basada en tokens y un modo más avanzado llamado enhance_query. Cuando se habilita, enhance_query expande la búsqueda para incluir términos relacionados y sinónimos, lo que aumenta la probabilidad de encontrar resultados pertinentes.
Para habilitar esta opción, configura el argumento opcional enhance_query=>true en la función SEARCH. Por ejemplo, la 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 la tokenización.
Puedes usar el mismo índice de búsqueda con enhance_query o sin él.
Google mejora continuamente los algoritmos de optimización de búsquedas. Como resultado, una búsqueda con enhance_query == true puede generar resultados ligeramente diferentes con el tiempo.
Cuando se habilita el modo enhance_query, es posible que aumente la cantidad de términos que busca la función SEARCH, lo que podría aumentar ligeramente la latencia.
Requisitos de la consulta en SQL
Existen varias condiciones que debe cumplir una consulta en SQL 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 un plan alternativo.
Las búsquedas deben cumplir con las siguientes condiciones:
Las funciones SEARCH y
SEARCH_SUBSTRINGrequieren un índice de búsqueda. Spanner no admite estas funciones en las consultas realizadas en la tabla base ni en los índices secundarios.Los índices particionados deben tener todas las columnas de partición vinculadas por una condición de igualdad en la cláusula
WHEREde la consulta.Por ejemplo, si un índice de búsqueda se define como
PARTITION BY x, y, la búsqueda debe tener una conjunción en la cláusulaWHEREdex = <parameter or constant> AND y = <parameter or constant>. El optimizador de consultas no considera ese índice de búsqueda si falta tal condición.Todas las columnas
TOKENLISTa las que hacen referencia los operadoresSEARCHySEARCH_SUBSTRINGdeben indexarse en el mismo índice de búsqueda.Por ejemplo, considera la siguiente definición de índice y tabla:
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 un solo índice de búsqueda que indexe
AlbumTitle_TokensyAlbumStudio_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 búsqueda
$1y$2, que se vinculan a "coche rápido" y "nota azul", respectivamente.SELECT albumid FROM albums WHERE spanner.search(albumtitle_tokens, $1) AND spanner.search(albumstudio_tokens, $2)Si la columna de ordenamiento es anulable, tanto el esquema como la consulta deben excluir las filas en las que la columna de ordenamiento sea NULL. Para obtener más detalles, consulta Orden de clasificación del índice de búsqueda.
Si el índice de búsqueda se filtra como NULL, la consulta debe incluir la misma expresión de filtrado como NULL que se usa en un índice. Consulta Índices de búsqueda filtrados por NULL para obtener más detalles.
Los índices de búsqueda y las funciones de búsqueda no se admiten en DML, DML particionado ni consultas particionadas.
Por lo general, los índices de búsqueda y las funciones de búsqueda se usan en transacciones de solo lectura. Si los requisitos de la aplicación permiten resultados desactualizados, es posible que puedas mejorar la latencia ejecutando búsquedas con una duración de desactualización de 10 segundos o más. Para obtener más información, consulta Cómo leer datos inactivos. Esto es especialmente útil para las búsquedas que se ramifican en muchas divisiones del índice.
No se recomiendan los índices de búsqueda ni las funciones de búsqueda en las transacciones de lectura y escritura.
Durante la ejecución, las búsquedas bloquean una partición de índice completa. Como resultado, una alta tasa de búsquedas en transacciones de lectura y escritura puede causar conflictos de bloqueo que generen 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 una consulta para que use un índice de búsqueda en una transacción de lectura y escritura, fallará 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 @{ALLOW_SEARCH_INDEXES_IN_TRANSACTION=TRUE} a nivel de la instrucción de GoogleSQL (pero las consultas siguen siendo propensas a conflictos de bloqueo).
Una vez que se cumplen las condiciones de elegibilidad 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.
Parámetros de consulta
Los argumentos de la búsqueda se especifican como un literal o un parámetro de búsqueda. Recomendamos usar parámetros de búsqueda para la búsqueda de texto completo en lugar de literales de cadena cuando los argumentos permiten el valor del parámetro de búsqueda.
Selección de índices
Por lo general, Spanner selecciona el índice más eficiente para una consulta con un modelado basado en costos. Sin embargo, la sugerencia FORCE_INDEX indica de forma explícita a Spanner que use un índice de búsqueda específico. Por ejemplo, el siguiente código muestra cómo forzar 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 apto, la consulta fallará, incluso si hay otros índices de búsqueda aptos.
Fragmentos en los resultados de la búsqueda
Un fragmento es un texto extraído de una cadena determinada que les brinda a los usuarios una idea del contenido de un resultado de la búsqueda y el motivo por el que el resultado es pertinente para su búsqueda.
Por ejemplo, Gmail usa resúmenes para indicar la parte de un correo electrónico que coincide con la búsqueda:

Generar un fragmento de la base de datos tiene varios beneficios:
- Comodidad: No necesitas implementar lógica para generar fragmentos a partir de una búsqueda.
- Eficiencia: Los resúmenes reducen el tamaño de la respuesta del servidor.
La función SNIPPET crea el fragmento. Devuelve la parte pertinente del valor de la cadena original junto con las posiciones de los caracteres que se deben destacar. Luego, el cliente puede elegir cómo mostrar el fragmento al usuario final (por ejemplo, con texto destacado o en negrita).
Por ejemplo, el siguiente código usa SNIPPET para recuperar 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')
¿Qué sigue?
- Obtén más información para clasificar los resultados de la búsqueda.
- Obtén más información para realizar una búsqueda de subcadena.
- Obtén más información para paginar los resultados de la búsqueda.
- Obtén más información para combinar búsquedas de texto completo y búsquedas que no son de texto.
- Obtén más información para buscar en varias columnas.