이 페이지에서는 전체 텍스트 검색에 패싯을 사용하는 방법을 설명합니다. 상호작용 필터링의 일부로 패싯은 잠재적인 필터 값과 해당 필터의 일치 항목 수입니다. 이 기능이 있는 웹사이트에서 검색어를 입력하면 탐색 메뉴에 결과 목록이 표시되고, 검색 결과를 좁히는 데 사용할 수 있는 패싯 목록과 각 카테고리에 맞는 결과 수가 표시됩니다.
예를 들어 'foo'라는 쿼리를 사용하여 앨범을 검색하면 수백 개의 결과가 표시될 수 있습니다. 장르 패싯이 있는 경우 '록 (250)', 'R&B (50)', '팝 (150)'과 같은 장르별로 선택할 수 있습니다.
Spanner 전체 텍스트 검색에서는 필터링과 필터링된 개수 계산 모두에 표준 SQL 표현식과 전체 텍스트 검색 함수를 사용할 수 있습니다. 패싯을 사용하기 위해 특수 구문을 사용할 필요는 없습니다.
전체 텍스트 검색에 사용할 패싯 추가
다음 예시에서는 앨범 테이블을 만들고 각 앨범의 제목을 토큰화합니다. 이 표는 이 페이지의 예시에 사용됩니다.
GoogleSQL
CREATE TABLE Albums (
AlbumId INT64 NOT NULL,
Title STRING(MAX),
Rating INT64,
Genres ARRAY<STRING(MAX)>,
Likes INT64 NOT NULL,
Title_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(Title)) HIDDEN,
) PRIMARY KEY(AlbumId);
PostgreSQL
CREATE TABLE albums (
albumid bigint NOT NULL,
title text,
rating bigint,
genres text[],
likes bigint NOT NULL,
title_tokens spanner.TOKENLIST GENERATED ALWAYS AS (spanner.TOKENIZE_FULLTEXT(Title)) VIRTUAL HIDDEN,
PRIMARY KEY(albumid));
Title_Tokens
에 검색 색인을 만듭니다. 선택적으로 패싯을 계산하는 동안 기본 테이블에 대한 백조인을 방지하기 위해 검색 색인에 Title
, Genres
, Rating
을 저장할 수 있습니다.
GoogleSQL
CREATE SEARCH INDEX AlbumsIndex
ON Albums (Title_Tokens)
STORING (Title, Genres, Rating)
ORDER BY Likes DESC;
PostgreSQL
CREATE SEARCH INDEX albumsindex
ON albums (title_tokens)
INCLUDE (title, genres, rating)
ORDER BY likes DESC
이 예에서는 다음 데이터를 테이블에 삽입합니다.
GoogleSQL
INSERT INTO Albums (AlbumId, Title, Rating, Genres, Likes) VALUES
(1, "The Foo Strike Again", 5, ["Rock", "Alternative"], 600),
(2, "Who are the Who?", 5, ["Progressive", "Indie"], 200),
(3, "No Foo For You", 4, ["Metal", "Alternative"], 50)
PostgreSQL
INSERT INTO albums (albumid, title, rating, genres, likes) VALUES
(1, 'The Foo Strike Again', 5,'{"Rock", "Alternative"}', 600),
(2, 'Who are the Who?', 5,'{"Progressive", "Indie"}', 200),
(3, 'No Foo For You', 4,'{"Metal", "Alternative"}', 50)
단일 패싯의 개수 값 가져오기
이 예시에서는 Rating 패싯에서 패싯 수를 실행하는 방법을 보여줍니다. Albums 테이블의 Title_Tokens 열에서 'foo'에 대한 텍스트 검색을 실행합니다.
GoogleSQL
SELECT Rating, COUNT(*) AS result_count
FROM Albums
WHERE SEARCH(Title_Tokens, "foo")
GROUP BY Rating
ORDER BY Rating DESC
| Rating | result_count |
|--------|--------------|
| 5 | 1 |
| 4 | 1 |
PostgreSQL
SELECT rating, COUNT(*) AS result_count
FROM albums
WHERE spanner.SEARCH(title_tokens, 'foo')
GROUP BY rating
ORDER BY rating DESC;
| rating | result_count |
|--------|--------------|
| 5 | 1 |
| 4 | 1 |
여러 패싯의 개수 값 가져오기
이 예에서는 여러 패싯에서 패싯 수를 실행하는 단계를 보여줍니다. 다음 작업을 실행합니다.
- 초기 검색 결과를 가져옵니다.
Albums
테이블의Title_Tokens
열에서 'foo'를 텍스트 검색합니다. - 패싯 수 계산: 그런 다음
Rating
및Genres
패싯의 수를 계산합니다.
GoogleSQL
WITH search_results AS (
SELECT AlbumId, Title, Genres, Rating, Likes
FROM Albums
WHERE SEARCH(Title_Tokens, "foo")
ORDER BY Likes DESC, AlbumId
LIMIT 10000
)
SELECT
-- Result set #1: First page of search results
ARRAY(
SELECT AS STRUCT *
FROM search_results
ORDER BY Likes DESC, AlbumId
LIMIT 50
) as result_page,
-- Result set #2: Number of results by rating
ARRAY(
SELECT AS STRUCT Rating, COUNT(*) as result_count
FROM search_results
GROUP BY Rating
ORDER BY result_count DESC, Rating DESC
) as rating_counts,
-- Result set #3: Number of results for top 5 genres
ARRAY(
SELECT AS STRUCT genre, COUNT(*) as result_count
FROM search_results
JOIN UNNEST(Genres) genre
GROUP BY genre
ORDER BY result_count DESC, genre
LIMIT 5
) as genres_counts
PostgreSQL
WITH search_results AS (
SELECT albumid, title, genres, rating, likes
FROM albums
WHERE spanner.SEARCH(title_tokens, 'foo')
ORDER BY likes DESC, albumid
LIMIT 10000
)
-- The pattern ARRAY(SELECT TO_JSONB ...) enables returning multiple nested
-- result sets in the same query.
SELECT
-- Result set #1: First page of search results
ARRAY(
SELECT JSONB_BUILD_OBJECT(
'albumid', albumid,
'title', title,
'genres', genres,
'rating', rating,
'likes', likes
)
FROM search_results
ORDER BY likes DESC, albumid
LIMIT 50
) as result_page,
-- Result set #2: Number of results by rating
ARRAY(
SELECT JSONB_BUILD_OBJECT(
'rating', rating,
'result_count', COUNT(*)
)
FROM search_results
GROUP BY rating
ORDER BY COUNT(*) DESC, rating DESC
) as rating_counts,
-- Result set #3: Number of results for top 5 genres
ARRAY(
SELECT JSONB_BUILD_OBJECT(
'genre', genre,
'result_count', COUNT(*)
)
FROM
search_results,
UNNEST(genres) AS genre
GROUP BY genre
ORDER BY COUNT(*) DESC, genre
LIMIT 5
) as genres_counts
특히 이 예에서는 다음을 수행합니다.
WITH search_results AS (...)
은 결과의 첫 페이지와 패싯 계산에 사용할 초기 검색 결과를 많이 수집합니다.SEARCH(Title_Tokens, "foo")
은 기본 검색어입니다.LIMIT 10000
은 결과 집합을 10,000으로 줄여 검색 비용을 제한합니다. 수백만 개의 결과를 반환할 수 있는 매우 광범위한 검색의 경우 전체 데이터 세트에서 정확한 패싯 수를 계산하는 데 비용이 많이 들 수 있습니다. 검색 결과를 제한하면 쿼리에서 대략적인 (하한) 패싯 수를 빠르게 제공할 수 있습니다. 즉, 개수는 최소한 그만큼의 결과를 반영하지만 10,000개 한도를 초과하는 일치하는 결과가 더 있을 수 있습니다.result_page
하위 쿼리는 사용자에게 표시되는 검색 결과의 첫 페이지를 생성합니다.Likes
및AlbumId
로 정렬된search_results
에서 상위 50개 레코드만 선택합니다. 사용자에게 처음에 표시되는 내용입니다.rating_counts
하위 쿼리는Rating
의 패싯 수를 계산합니다.search_results
의 모든 레코드를Rating
별로 그룹화하고 각 평가 카테고리에 속하는 결과 수를 계산합니다.genres_counts
하위 쿼리는Genres
의 패싯 수를 계산합니다. 배열이므로UNNEST(Genres)
로 결합하여 배열 내 각 장르를 집계할 별도의 행으로 처리합니다.
후속 페이지 가져오기
초기 패싯 쿼리 후 연속 페이지를 쿼리할 때 첫 번째 페이지에서 반환된 패싯 수를 재사용할 수 있습니다.
페이지로 나누는 방법에 관한 자세한 내용은 키 기반 페이지로 나누기 사용을 참고하세요.