이 페이지에서는 전체 텍스트 검색에서 패싯을 사용하는 방법을 설명합니다. 패싯은 상호작용 필터링의 일부로, 잠재적인 필터 값과 해당 필터에 일치하는 항목 수를 의미합니다. 이 기능이 있는 웹사이트에서는 검색어를 입력하면 탐색 메뉴에 결과 목록이 표시되며, 각 카테고리별 결과 수와 함께 검색 결과를 좁히는 데 사용할 수 있는 패싯 목록이 표시됩니다.
예를 들어 "foo"라는 쿼리를 사용해 앨범을 검색하면 수백 개의 결과가 반환될 수 있습니다. 장르 패싯이 있는 경우 "록(250)," "알앤비(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)를 사용해 배열 내 각 장르를 개별 행으로 처리하여 카운트를 수행합니다.
후속 페이지 검색
초기 패싯 쿼리 이후 연속된 페이지를 쿼리할 때는 첫 번째 페이지에서 반환된 패싯 카운트를 재사용할 수 있습니다.
페이지로 나누는 방법에 대한 자세한 내용은 키 기반 페이지로 나누기 사용을 참조하세요.