Menggabungkan TOKENLIST

Halaman ini menjelaskan cara menggabungkan TOKENLIST di indeks penelusuran saat Anda menyiapkan skema atau dalam kueri penelusuran saat melakukan penelusuran teks lengkap di Spanner.

Menggabungkan TOKENLIST dalam indeks penelusuran

Terkadang, Anda memerlukan aplikasi untuk menelusuri di seluruh kolom individual. Di waktu lain, aplikasi perlu menelusuri semua kolom. Misalnya, dalam tabel dengan dua kolom string, Anda mungkin ingin aplikasi Anda menelusuri kedua kolom tanpa membedakan dari kolom mana kecocokan berasal.

Di Spanner, ada dua cara untuk melakukannya:

  1. Tokenisasi kata secara terpisah dan gabungkan TOKENLIST yang dihasilkan (direkomendasikan).
  2. Gabungkan string dan tokenisasi hasilnya.

Dengan pendekatan kedua, ada dua masalah:

  1. Jika Anda ingin mengindeks Title atau Studio satu per satu, selain mengindeksnya dalam TOKENLIST gabungan, teks yang sama akan di-tokenisasi dua kali. Hal ini menyebabkan transaksi menggunakan lebih banyak resource.
  2. Penelusuran frasa mencakup kedua kolom. Misalnya, jika @p disetel ke "Blue Note", maka akan cocok dengan baris yang berisi Title="Big Blue Note" dan Studio="Blue Note Studios".

Pendekatan pertama memecahkan masalah ini karena frasa hanya cocok dengan satu kolom dan setiap kolom string hanya di-tokenisasi satu kali jika TOKENLIST individu dan gabungan diindeks. Meskipun setiap kolom string hanya di-tokenisasi satu kali, TOKENLIST yang dihasilkan disimpan secara terpisah dalam indeks.

Lakukan tokenisasi kata secara terpisah dan gabungkan TOKENLIST

Contoh berikut melakukan tokenisasi setiap kata dan menggunakan TOKENLIST_CONCAT untuk menggabungkan 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 menggunakan spanner.tokenlist_concat untuk penggabungan. Parameter kueri $1 terikat ke '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);

Perhatikan bahwa tokenlist_concat tidak memanggil title_tokens atau studio_tokens, tetapi memanggil spanner.tokenize_fulltext(title) dan spanner.tokenize_fulltext(studio). Hal ini karena PostgreSQL tidak mendukung pereferensian kolom yang dihasilkan yang berada dalam kolom yang dihasilkan lainnya. spanner.tokenlist_concat perlu memanggil fungsi tokenisasi dan tidak mereferensikan kolom tokenlist secara langsung.

Penggabungan TOKENLIST juga dapat diterapkan sepenuhnya di sisi kueri. Untuk mengetahui informasi selengkapnya, lihat Penggabungan TOKENLIST sisi kueri.

TOKENLIST_CONCAT didukung untuk penelusuran teks lengkap dan substring. Spanner tidak mengizinkan Anda menggabungkan jenis tokenisasi, seperti TOKENIZE_FULLTEXT dan TOKENIZE_SUBSTRING dalam panggilan TOKENLIST_CONCAT yang sama.

Di GoogleSQL, definisi kolom teks TOKENLIST dapat diubah di kolom yang tidak disimpan untuk menambahkan kolom lainnya. Hal ini berguna jika Anda ingin menambahkan kolom lain ke TOKENLIST_CONCAT. Mengubah ekspresi kolom yang dihasilkan tidak mengisi ulang baris yang ada dalam indeks.

Menggabungkan string dan melakukan tokenisasi pada hasilnya

Contoh berikut menggabungkan string dan melakukan tokenisasi pada hasilnya:

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);

Penggabungan TOKENLIST sisi kueri

Kelemahan mengindeks TOKENLIST yang digabungkan adalah peningkatan biaya penyimpanan dan penulisan. Setiap token kini disimpan di disk dua kali: sekali dalam daftar postingan TOKENLIST aslinya, dan sekali dalam daftar postingan TOKENLIST gabungan. Penggabungan sisi kueri kolom TOKENLIST menghindari biaya ini, tetapi kueri menggunakan lebih banyak resource komputasi.

Untuk menggabungkan beberapa TOKENLIST, gunakan fungsi TOKENLIST_CONCAT dalam kueri SEARCH. Untuk bagian ini, kita menggunakan contoh skema berikut:

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);

Kueri berikut menelusuri baris yang memiliki token "biru" dan "catatan" di mana saja dalam kolom Title dan Studio. Hal ini mencakup baris dengan "blue" dan "note" di kolom Title, "blue" dan "note" di kolom Studio, serta "blue" di kolom Title dan "note" di kolom Studio, atau sebaliknya.

GoogleSQL

SELECT AlbumId
FROM Albums
WHERE SEARCH(TOKENLIST_CONCAT([AlbumTitle_Tokens, Studio_Tokens]), 'blue note')

PostgreSQL

Contoh ini menggunakan spanner.search dengan spanner.tokenlist_concat.

SELECT albumid
FROM albums
WHERE spanner.search(spanner.tokenlist_concat(ARRAY[albumtitle_tokens, studio_tokens]), 'blue note')

Penggabungan TOKENLIST sisi penulisan dan sisi kueri menghasilkan hasil yang identik. Pilihan antara keduanya adalah kompromi antara biaya disk dan biaya kueri.

Atau, aplikasi dapat menelusuri beberapa kolom TOKENLIST dan menggunakan OR bersama dengan fungsi 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')

Namun, hal ini memiliki semantik yang berbeda. Tidak cocok dengan album yang memiliki AlbumTitle_Tokens "biru", tetapi tidak "catatan", dan Studio_Tokens memiliki "catatan", tetapi tidak "biru".

Langkah berikutnya