이 페이지에서는 Spanner에서 전체 텍스트 검색의 검색 결과 순위를 지정하는 방법을 설명합니다.
Spanner는 정교한 순위 함수 만들기의 구성 요소를 제공하는 적합성 점수 계산을 지원합니다. 이러한 점수는 검색어 빈도 및 기타 맞춤설정 가능한 옵션을 기반으로 쿼리에 대한 결과의 관련성을 계산합니다.
다음 예시에서는 SCORE 함수를 사용하여 순위 기반 검색을 실행하는 방법을 보여줍니다.
GoogleSQL
SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, "fifth symphony")
ORDER BY SCORE(AlbumTitle_Tokens, "fifth symphony") DESC
PostgreSQL
이 예시에서는 spanner.score와 함께 spanner.search를 사용합니다.
SELECT albumid
FROM albums
WHERE spanner.search(albumtitle_tokens, 'fifth symphony')
ORDER BY spanner.score(albumtitle_tokens, 'fifth symphony') DESC
SCORE 함수로 검색어 점수 매기기
SCORE 함수는 각 검색어의 점수를 계산한 후 점수를 결합합니다. 용어별 점수는 용어 빈도- 역문서 빈도(TF/IDF)를 기반으로 대략적으로 계산됩니다. 점수는 레코드의 최종 순서의 한 구성요소입니다. 쿼리는 이 점수를 적합성 점수를 조정하는 최신성 등 다른 신호와 결합합니다.
현재 구현에서는 TF/IDF의 IDF 부분은 enhance_query=>true가 사용되는 경우에만 사용할 수 있습니다. 특정 검색 색인이 아닌 Google 검색에서 사용하는 전체 웹 코퍼스를 기반으로 단어의 상대적 빈도를 계산합니다. 쿼리 개선이 사용 설정되지 않은 경우 점수 산정에서 용어 빈도(TF) 구성요소만 사용됩니다(즉, IDF 용어가 1로 설정됨).
SCORE 함수는 Spanner가 정렬 순서를 설정하는 데 사용하는 관련성 점수 역할을 하는 값을 반환합니다. 이는 단독으로 의미가 없습니다. 점수가 높을수록 검색어와 더 잘 일치합니다.
일반적으로 query 및 enhance_query와 같은 인수는 검색 및 순위 지정 일관성을 보장하기 위해 SEARCH 함수와 SCORE 함수에서 동일합니다.
이를 실행하는 권장 방법은 문자열 리터럴 대신 쿼리 파라미터와 함께 이러한 인수를 사용하고 SEARCH 및 SCORE 함수에 동일한 쿼리 파리미터를 지정하는 것입니다.
여러 열 점수 매기기
Spanner는 SCORE 함수를 사용하여 각 필드에 개별적으로 점수를 매깁니다. 그런 다음 쿼리는 이러한 개별 점수를 함께 결합합니다. 일반적으로는 개별 점수를 합산한 후 사용자가 제공한 필드 가중치(SQL 쿼리 파라미터를 사용하여 제공됨)에 따라 점수를 올릴 수 있습니다.
예를 들어 다음 쿼리는 두 개의 SCORE 함수의 출력을 결합합니다.
GoogleSQL
SELECT AlbumId
FROM Albums
WHERE SEARCH(Title_Tokens, @p1) AND SEARCH(Studio_Tokens, @p2)
ORDER BY SCORE(Title_Tokens, @p1) * @titleweight + SCORE(Studio_Tokens, @p2) * @studioweight
LIMIT 25
PostgreSQL
이 예시에서는 각각 'fifth symphony' 및 'blue note'에 바인딩된 쿼리 파라미터 $1 및 $2를 사용합니다.
SELECT albumid
FROM albums
WHERE spanner.search(title_tokens, $1) AND spanner.search(studio_tokens, $2)
ORDER BY spanner.score(title_tokens, $1) * $titleweight
+ spanner.score(studio_tokens, $2) * $studioweight
LIMIT 25
다음 예시에서는 두 가지 부스트 파라미터를 추가합니다.
- 최신성(
FreshnessBoost)은(1 + @freshnessweight * GREATEST(0, 30 - DaysOld) / 30)공식을 통해 점수를 높입니다. - 인기도(
PopularityBoost)는 점수에(1 + IF(HasGrammy, @grammyweight, 0)계수를 곱하여 점수를 높입니다.
가독성을 위해 쿼리에서 WITH 연산자를 사용합니다.
GoogleSQL
SELECT AlbumId
FROM Albums
WHERE SEARCH(Title_Tokens, @p1) AND SEARCH(Studio_Tokens, @p2)
ORDER BY WITH(
TitleScore AS SCORE(Title_Tokens, @p1) * @titleweight,
StudioScore AS SCORE(Studio_Tokens, @p2) * @studioweight,
DaysOld AS (UNIX_MICROS(CURRENT_TIMESTAMP()) - ReleaseTimestamp) / 8.64e+10,
FreshnessBoost AS (1 + @freshnessweight * GREATEST(0, 30 - DaysOld) / 30),
PopularityBoost AS (1 + IF(HasGrammy, @grammyweight, 0)),
(TitleScore + StudioScore) * FreshnessBoost * PopularityBoost)
LIMIT 25
PostgreSQL
이 예시에서는 titlequery, studioquery, titleweight, studioweight, grammyweight, freshnessweight에 지정된 값에 바인딩된 쿼리 파라미터 $1, $2, $3, $4, $5, $6를 사용합니다.
SELECT albumid
FROM
(
SELECT
albumid,
spanner.score(title_tokens, $1) * $3 AS titlescore,
spanner.score(studio_tokens, $2) * $4 AS studioscore,
(extract(epoch FROM current_timestamp) * 10e+6 - releasetimestamp) / 8.64e+10 AS daysold,
(1 + CASE WHEN hasgrammy THEN $5 ELSE 0 END) AS popularityboost
FROM albums
WHERE spanner.search(title_tokens, $1) AND spanner.search(studio_tokens, $2)
) AS subquery
ORDER BY (subquery.TitleScore + subquery.studioscore)
* (1 + $6 * greatest(0, 30 - subquery.daysold) / 30) * subquery.popularityboost
LIMIT 25
TOKENLIST_CONCAT은 검색과 점수 산정 모두에 사용할 수 있으므로 적절한 경우 쿼리를 간소화할 수 있습니다.
GoogleSQL
SELECT AlbumId
FROM Albums
WHERE SEARCH(TOKENLIST_CONCAT([Title_Tokens, Studio_Tokens]), @p)
ORDER BY SCORE(TOKENLIST_CONCAT([Title_Tokens, Studio_Tokens]), @p)
LIMIT 25
PostgreSQL
이 예시에서는 spanner.tokenlist_concat을 사용합니다.
쿼리 파라미터 $1가 'blue note'에 바인딩됩니다.
SELECT albumid
FROM albums
WHERE spanner.search(spanner.tokenlist_concat(ARRAY[title_tokens, studio_tokens]), $1)
ORDER BY spanner.score(spanner.tokenlist_concat(ARRAY[title_tokens, studio_tokens]), $1)
LIMIT 25
검색어 순서 일치 부스트
Spanner는 쿼리에 표시되는 순서와 동일한 순서로 검색어가 포함된 값의 SCORE 함수 출력에 배수 부스트를 적용합니다. 이 부스트에는 부분 일치와 정확한 일치의 두 가지 버전이 있습니다. 부분 일치 부스트는 다음과 같은 경우에 적용됩니다.
TOKENLIST에 쿼리의 모든 원래 검색어가 포함되어야 합니다.- 토큰이 서로 인접하며 쿼리에 표시된 순서와 동일해야 합니다.
결합, 분정, 구문에는 몇 가지 특수한 규칙이 있습니다.
- 부정이 포함된 쿼리는 부분 일치 부스트를 받을 수 없습니다.
- 결합이 포함된 검색어는 결합의 일부가 적절한 위치에 표시되면 부스트를 받습니다.
- 구문이 포함된 쿼리는 구문이
TOKENLIST에 표시되면 부스트를 받고, 쿼리에서 구문 왼쪽에 있는 용어가TOKENLIST에서 구문 왼쪽에 표시되며, 구문 오른쪽에 있는 용어에도 동일하게 적용됩니다.
Spanner는 이전 규칙이 모두 true이고 쿼리의 첫 번째 및 마지막 토큰이 문서의 첫 번째 및 마지막 토큰인 경우 정확한 일치 부스트를 적용합니다.
문서 예시: Bridge Over Troubled Water
| 쿼리 | 부스트 적용됨 |
|---|---|
| Bridge Troubled | 부스트 없음 |
| Bridge Over - other water | 부스트 없음 |
| Bridge (Over OR Troubled) Water | 부스트 없음 |
| Bridge Over | 부분 부스트 |
| Bridge Over (Troubled OR Water) | 부분 부스트 |
| Bridge Over Troubled Water | 일치 부스트 |
| Bridge "Over Troubled" Water | 일치 부스트 |
| Bridge ("Over Troubled" OR missingterm) Water | 일치 부스트 |
검색 깊이 제한
검색 색인에는 수백만 개의 문서가 포함되는 경우가 많습니다. 조건자의 선택성이 낮은 쿼리의 경우 모든 결과를 순위 지정하는 것은 실용성이 떨어집니다. 스코어링 쿼리에는 일반적으로 두 가지 제한이 있습니다.
- 검색 깊이 제한: 점수를 매길 최대 행 수입니다.
- 결과 세트 크기 제한: 쿼리가 반환해야 하는 최대 행 수입니다(일반적으로 페이지 크기).
쿼리는 SQL 하위 쿼리를 사용하여 검색 깊이를 제한할 수 있습니다.
GoogleSQL
SELECT *
FROM (
SELECT AlbumId, Title_Tokens
FROM Albums
WHERE SEARCH(Title_Tokens, @p1)
ORDER BY ReleaseTimestamp DESC
LIMIT @retrieval_limit
)
ORDER BY SCORE(Title_Tokens, @p1)
LIMIT @page_size
PostgreSQL
이 예시에서는 title_query, retrieval_limit, page_size에 지정된 값에 각각 바인딩된 쿼리 파라미터 $1, $2, $3를 사용합니다.
SELECT *
FROM (
SELECT albumid, title_tokens
FROM albums
WHERE spanner.search(title_tokens, $1)
ORDER BY releasetimestamp DESC
LIMIT $2
) AS subquery
ORDER BY spanner.score(subquery.title_tokens, $1)
LIMIT $3
이는 Spanner가 가장 중요한 순위 결정 신호를 사용하여 색인을 정렬하는 경우에 특히 효과적입니다.
다음 단계
- 전체 텍스트 검색어 알아보기
- 하위 문자열 검색 수행 방법 알아보기
- 검색결과를 페이지로 나누는 방법 알아보기
- 전체 텍스트 및 비텍스트 쿼리 혼합 방법 알아보기
- 여러 열 검색 방법 알아보기