이 페이지에서는 스키마를 설정할 때 검색 색인에서 또는 Spanner에서 전체 텍스트 검색을 실행할 때 검색어에서 TOKENLIST
를 연결하는 방법을 설명합니다.
검색 색인에서 TOKENLIST 결합
때로는 애플리케이션에서 개별 필드를 검색해야 하는 경우가 있습니다. 반면에 애플리케이션에서 모든 필드를 검색해야 하는 경우도 있습니다. 예를 들어 두 개의 문자열 열이 있는 테이블에서 애플리케이션이 일치 항목이 어느 열에서 비롯되었는지 구분하지 않고 두 열을 모두 검색하도록 할 수 있습니다.
Spanner에서는 다음 두 가지 방법으로 이 작업을 수행할 수 있습니다.
두 번째 접근 방식에는 두 가지 문제가 있습니다.
Title
또는Studio
를 개별적으로 색인화하려면 결합된TOKENLIST
에 색인화하는 것 외에도 동일한 텍스트가 두 번 토큰화됩니다. 이로 인해 트랜잭션에서 더 많은 리소스를 사용하게 됩니다.- 구문 검색은 두 필드 모두에 적용됩니다. 예를 들어
@p
가"Blue Note"
로 설정되면Title
='Big Blue Note' 및Studio
='Blue Note Studios'가 모두 포함된 행과 일치합니다.
첫 번째 접근 방식은 구문이 하나의 필드에만 일치하고 각 문자열 필드는 개별 및 결합된 TOKENLIST
가 모두 색인 생성된 경우에만 한 번 토큰화되므로 이러한 문제를 해결합니다. 각 문자열 필드는 한 번만 토큰화되더라도 결과 TOKENLIST
는 색인에 별도로 저장됩니다.
단어를 개별적으로 토큰화하여 TOKENLIST
연결
다음 예에서는 각 단어를 토큰화하고 TOKENLIST_CONCAT
을 사용하여 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은 연결에 spanner.tokenlist_concat
을 사용합니다. 쿼리 매개변수 $1
은 '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);
tokenlist_concat
은 title_tokens
또는 studio_tokens
를 호출하지 않고 대신 spanner.tokenize_fulltext(title)
및 spanner.tokenize_fulltext(studio)
를 호출한다는 점에 유의하세요. 이는 PostgreSQL이 다른 생성된 열 내에 있는 생성된 열 참조를 지원하지 않기 때문입니다. spanner.tokenlist_concat
는 tokenize 함수를 호출해야 하며 tokenlist 열을 직접 참조해서는 안 됩니다.
TOKENLIST
연결은 쿼리 측에서 전적으로 구현할 수도 있습니다.
자세한 내용은 쿼리 측 TOKENLIST
연결을 참조하세요.
TOKENLIST_CONCAT
은 전체 텍스트 검색과 하위 문자열 검색 모두에서 지원됩니다.
Spanner에서는 동일한 TOKENLIST_CONCAT
호출에서 TOKENIZE_FULLTEXT
및 TOKENIZE_SUBSTRING
같은 토큰화 유형을 혼합할 수 없습니다.
GoogleSQL에서는 저장되지 않은 열에서 텍스트 TOKENLIST
열의 정의를 변경하여 열을 추가할 수 있습니다. TOKENLIST_CONCAT
에 열을 추가하려는 경우에 유용합니다. 생성된 열 표현식을 변경해도 색인의 기존 행이 백필되지 않습니다.
문자열 연결 및 결과 토큰화
다음 예시에서는 문자열을 연결하고 결과를 토큰화합니다.
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);
쿼리 측 TOKENLIST
연결
연결된 TOKENLIST
에 색인을 생성하면 스토리지 및 쓰기 비용이 증가한다는 단점이 있습니다. 이제 각 토큰은 원래 TOKENLIST
의 게시 목록에 한 번, 결합된 TOKENLIST
의 게시 목록에 한 번, 디스크에 두 번 저장됩니다. TOKENLIST
열의 쿼리 측 연결은 이 비용을 피할 수 있지만 쿼리에는 더 많은 컴퓨팅 리소스가 사용됩니다.
여러 개의 TOKENLIST
를 연결하려면 SEARCH
쿼리에서 TOKENLIST_CONCAT
함수를 사용합니다. 이 섹션에서는 다음 샘플 스키마를 사용합니다.
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);
다음 쿼리는 Title
및 Studio
열의 어느 곳에서나 'blue' 및 'note' 토큰이 있는 행을 검색합니다. 여기에는 Title
열에 'blue' 및 'note'가 모두 포함된 행, Studio
열에 'blue' 및 'note'가 모두 포함된 행, Title
열에 'blue'가 있고 Studio
열에 'note'가 있거나 그 반대인 행이 포함됩니다.
GoogleSQL
SELECT AlbumId
FROM Albums
WHERE SEARCH(TOKENLIST_CONCAT([AlbumTitle_Tokens, Studio_Tokens]), 'blue note')
PostgreSQL
이 예시에서는 spanner.tokenlist_concat
와 함께 spanner.search
을 사용합니다.
SELECT albumid
FROM albums
WHERE spanner.search(spanner.tokenlist_concat(ARRAY[albumtitle_tokens, studio_tokens]), 'blue note')
쓰기 측과 쿼리 측 TOKENLIST
연결은 동일한 결과를 생성합니다.
두 가지 중에서 선택할 때는 디스크 비용과 쿼리 비용 간의 절충이 이루어집니다.
또는 애플리케이션이 여러 TOKENLIST
열을 검색하고 SEARCH
함수와 함께 OR
을 사용할 수 있습니다.
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')
그러나 시맨틱스는 다릅니다. AlbumTitle_Tokens
에는 'blue'가 있지만 'note'는 없고 Studio_Tokens
에는 'note'가 있지만 'blue'가 없는 앨범과는 일치하지 않습니다.
다음 단계
- 전체 텍스트 검색어 알아보기
- 검색 색인 알아보기