Tetap teratur dengan koleksi
Simpan dan kategorikan konten berdasarkan preferensi Anda.
Halaman ini menjelaskan cara melakukan penelusuran yang menggabungkan data teks lengkap dan non-teks.
Melakukan penelusuran teks lengkap dan non-teks campuran
Indeks penelusuran mendukung
kolom teks lengkap, pencocokan persis, kolom numerik, dan kolom JSON/JSONB. Anda dapat menggabungkan
kondisi teks dan non-teks dalam klausa WHERE, mirip dengan kueri penelusuran
multi-kolom. Pengoptimal kueri mencoba mengoptimalkan predikat non-teks dengan
indeks penelusuran. Jika tidak memungkinkan, Spanner akan mengevaluasi
kondisi untuk setiap baris yang cocok dengan indeks penelusuran. Kolom yang dirujuk dan tidak
disimpan dalam indeks penelusuran diambil dari tabel dasar.
Perilaku kueri pada tabel ini mencakup hal berikut:
Rating dan Genres disertakan dalam indeks penelusuran.
Spanner mempercepat kondisi menggunakan daftar posting
indeks penelusuran. ARRAY_INCLUDES_ANY, ARRAY_INCLUDES_ALL adalah fungsi GoogleSQL dan tidak didukung untuk dialek PostgreSQL.
Kueri dapat menggabungkan konjungsi, disjungsi, dan negasi dengan cara apa pun,
termasuk menggabungkan predikat teks lengkap dan non-teks. Kueri ini sepenuhnya
dipercepat oleh indeks penelusuran.
Likes disimpan dalam indeks, tetapi skema tidak meminta
Spanner untuk membuat indeks token untuk kemungkinan nilainya.
Oleh karena itu, predikat teks lengkap di Title dan predikat non-teks di
Rating dipercepat, tetapi predikat di Likes tidak. Di
Spanner, kueri mengambil semua dokumen dengan istilah "mobil"
di Title dan rating lebih dari 4, lalu memfilter dokumen yang
tidak memiliki setidaknya 1.000 suka. Kueri ini menggunakan banyak resource jika hampir
semua album memiliki istilah "mobil" dalam judulnya dan hampir semuanya memiliki
rating 5, tetapi hanya sedikit album yang memiliki 1.000 suka. Dalam kasus tersebut, pengindeksan
Likes mirip dengan Rating akan menghemat resource.
Cover tidak disimpan dalam indeks. Kueri berikut melakukan
gabungan balik
antara AlbumsIndex dan Albums untuk mengambil Cover untuk semua album yang cocok.
[[["Mudah dipahami","easyToUnderstand","thumb-up"],["Memecahkan masalah saya","solvedMyProblem","thumb-up"],["Lainnya","otherUp","thumb-up"]],[["Sulit dipahami","hardToUnderstand","thumb-down"],["Informasi atau kode contoh salah","incorrectInformationOrSampleCode","thumb-down"],["Informasi/contoh yang saya butuhkan tidak ada","missingTheInformationSamplesINeed","thumb-down"],["Masalah terjemahan","translationIssue","thumb-down"],["Lainnya","otherDown","thumb-down"]],["Terakhir diperbarui pada 2025-09-03 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)."]]