Misture consultas de texto completo e não de texto
Mantenha tudo organizado com as coleções
Salve e categorize o conteúdo com base nas suas preferências.
Esta página descreve como realizar uma pesquisa que mistura dados de texto completo e não
texto.
Realizar uma pesquisa mista de texto completo e não textual
Os índices de pesquisa oferecem suporte
a texto completo, correspondência exata, colunas numéricas e colunas JSON/JSONB. É possível combinar
condições de texto e não texto na cláusula WHERE de forma semelhante a consultas de pesquisa
de várias colunas. O otimizador de consulta tenta otimizar predicados não de texto com um
índice de pesquisa. Se isso não for possível, o Spanner vai avaliar a
condição para cada linha que corresponder ao índice de pesquisa. As colunas referenciadas que não são armazenadas no índice de pesquisa são extraídas da tabela base.
O comportamento das consultas nessa tabela inclui o seguinte:
Rating e Genres são incluídos no índice de pesquisa.
O Spanner acelera as condições usando listas de publicação de índices de pesquisa. ARRAY_INCLUDES_ANY e ARRAY_INCLUDES_ALL são funções do GoogleSQL e não são compatíveis com o dialeto do PostgreSQL.
A consulta pode combinar conjunções, disjunções e negações de qualquer maneira,
inclusive misturando predicados de texto completo e não de texto. Essa consulta é totalmente
acelerada pelo índice de pesquisa.
Likes é armazenado no índice, mas o esquema não solicita
que o Spanner crie um índice de token para os valores possíveis.
Portanto, o predicado de texto completo em Title e o predicado não de texto em
Rating são acelerados, mas o predicado em Likes não é. No
Spanner, a consulta busca todos os documentos com o termo "car"
no Title e uma classificação maior que 4. Em seguida, ela filtra os documentos que
não têm pelo menos 1.000 curtidas. Essa consulta usa muitos recursos se quase
todos os álbuns tiverem o termo "car" no título e quase todos tiverem uma
classificação de 5, mas poucos álbuns tiverem 1.000 curtidas. Nesses casos, a indexação de
Likes de forma semelhante a Rating economiza recursos.
Cover não é armazenado no índice. A consulta a seguir faz uma
junção reversa
entre AlbumsIndex e Albums para buscar Cover em todos os álbuns correspondentes.
[[["Fácil de entender","easyToUnderstand","thumb-up"],["Meu problema foi resolvido","solvedMyProblem","thumb-up"],["Outro","otherUp","thumb-up"]],[["Difícil de entender","hardToUnderstand","thumb-down"],["Informações incorretas ou exemplo de código","incorrectInformationOrSampleCode","thumb-down"],["Não contém as informações/amostras de que eu preciso","missingTheInformationSamplesINeed","thumb-down"],["Problema na tradução","translationIssue","thumb-down"],["Outro","otherDown","thumb-down"]],["Última atualização 2025-09-05 UTC."],[],[],null,["# Mix full-text and non-text queries\n\n| **Note:** This feature is available with the Spanner Enterprise edition and Enterprise Plus edition. For more information, see the [Spanner editions overview](/spanner/docs/editions-overview).\n\n\u003cbr /\u003e\n\nThis page describes how to perform a search that mixes full-text and non-text\ndata.\n\nPerform a mixed full-text and non-text search\n---------------------------------------------\n\n[Search indexes](/spanner/docs/full-text-search/search-indexes) support\nfull-text, exact match, numeric columns, and JSON/JSONB columns. You can combine\ntext and non-text conditions in the `WHERE` clause similarly to multi-column\nsearch queries. The query optimizer tries to optimize non-text predicates with a\nsearch index. If that's not possible, Spanner evaluates the\ncondition for every row that matches the search index. Referenced columns not\nstored in the search index are fetched from the base table.\n\nConsider the following example: \n\n### GoogleSQL\n\n CREATE TABLE Albums (\n AlbumId STRING(MAX) NOT NULL,\n Title STRING(MAX),\n Rating FLOAT64,\n Genres ARRAY\u003cSTRING(MAX)\u003e,\n Likes INT64,\n Cover BYTES(MAX),\n Title_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(Title)) HIDDEN,\n Rating_Tokens TOKENLIST AS (TOKENIZE_NUMBER(Rating)) HIDDEN,\n Genres_Tokens TOKENLIST AS (TOKEN(Genres)) HIDDEN\n ) PRIMARY KEY(AlbumId);\n\n CREATE SEARCH INDEX AlbumsIndex\n ON Albums(Title_Tokens, Rating_Tokens, Genres_Tokens)\n STORING (Likes);\n\n### PostgreSQL\n\nSpanner PostgreSQL support has the following\nlimitations:\n\n- `spanner.tokenize_number` function only supports the `bigint` type.\n- `spanner.token` doesn't support tokenizing arrays.\n\n CREATE TABLE albums (\n albumid character varying NOT NULL,\n title character varying,\n rating bigint,\n genres character varying NOT NULL,\n likes bigint,\n cover bytea,\n title_tokens spanner.tokenlist AS (spanner.tokenize_fulltext(title)) VIRTUAL HIDDEN,\n rating_tokens spanner.tokenlist AS (spanner.tokenize_number(rating)) VIRTUAL HIDDEN,\n genres_tokens spanner.tokenlist AS (spanner.token(genres)) VIRTUAL HIDDEN,\n PRIMARY KEY(albumid));\n\n CREATE SEARCH INDEX albumsindex\n ON albums(title_tokens, rating_tokens, genres_tokens)\n INCLUDE (likes);\n\nThe behavior of queries on this table include the following:\n\n- `Rating` and `Genres` are included in the search index.\n Spanner accelerates conditions using search index posting\n lists. `ARRAY_INCLUDES_ANY`, `ARRAY_INCLUDES_ALL` are GoogleSQL\n functions and are not supported for PostgreSQL dialect.\n\n SELECT Album\n FROM Albums\n WHERE Rating \u003e 4\n AND ARRAY_INCLUDES_ANY(Genres, ['jazz'])\n\n- The query can combine conjunctions, disjunctions, and negations in any way,\n including mixing full-text and non-text predicates. This query is fully\n accelerated by the search index.\n\n SELECT Album\n FROM Albums\n WHERE (SEARCH(Title_Tokens, 'car')\n OR Rating \u003e 4)\n AND NOT ARRAY_INCLUDES_ANY(Genres, ['jazz'])\n\n- `Likes` is stored in the index, but the schema doesn't request\n Spanner to build a token index for its possible values.\n Therefore, the full-text predicate on `Title` and non-text predicate on\n `Rating` is accelerated, but the predicate on `Likes` isn't. In\n Spanner, the query fetches all documents with the term \"car\"\n in the `Title` and a rating more than 4, then it filters documents that\n don't have at least 1000 likes. This query uses a lot of resources if almost\n all albums have the term \"car\" in their title and almost all of them have a\n rating of 5, but few albums have 1000 likes. In such cases, indexing\n `Likes` similarly to `Rating` saves resources.\n\n ### GoogleSQL\n\n SELECT Album\n FROM Albums\n WHERE SEARCH(Title_Tokens, 'car')\n AND Rating \u003e 4\n AND Likes \u003e= 1000\n\n ### PostgreSQL\n\n SELECT album\n FROM albums\n WHERE spanner.search(title_tokens, 'car')\n AND rating \u003e 4\n AND likes \u003e= 1000\n\n- `Cover` isn't stored in the index. The following query does a\n [back join](/spanner/docs/query-execution-plans#index_and_back_join_queries)\n between `AlbumsIndex` and `Albums` to fetch `Cover` for all matching albums.\n\n ### GoogleSQL\n\n SELECT AlbumId, Cover\n FROM Albums\n WHERE SEARCH(Title_Tokens, 'car')\n AND Rating \u003e 4\n\n ### PostgreSQL\n\n SELECT albumid, cover\n FROM albums\n WHERE spanner.search(title_tokens, 'car')\n AND rating \u003e 4\n\nWhat's next\n-----------\n\n- Learn about [full-text search queries](/spanner/docs/full-text-search/query-overview).\n- Learn how to [rank search results](/spanner/docs/full-text-search/ranked-search).\n- Learn how to [perform a substring search](/spanner/docs/full-text-search/substring-search).\n- Learn how to [paginate search results](/spanner/docs/full-text-search/paginate-search-results).\n- Learn how to [search multiple columns](/spanner/docs/full-text-search/search-multiple-columns)."]]