Esta página descreve como classificar os resultados da pesquisa de texto completo no Spanner.
O Spanner oferece suporte à computação de uma pontuação de atualidade, que fornece um bloco de construção para criar funções de classificação sofisticadas. Essas pontuações calculam a relevância de um resultado para uma consulta com base na frequência do termo da consulta e em outras opções personalizáveis.
O exemplo a seguir mostra como realizar uma pesquisa classificada usando a função
SCORE
:
GoogleSQL
SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, "fifth symphony")
ORDER BY SCORE(AlbumTitle_Tokens, "fifth symphony") DESC
PostgreSQL
Este exemplo usa spanner.search
com
spanner.score
.
SELECT albumid
FROM albums
WHERE spanner.search(albumtitle_tokens, 'fifth symphony')
ORDER BY spanner.score(albumtitle_tokens, 'fifth symphony') DESC
Avaliar termos de consulta com a função SCORE
A função SCORE
calcula uma pontuação para cada termo de consulta e as combina. A
pontuação por termo é baseada aproximadamente na frequência de termo e frequência inversa de documento
(TF/IDF). A pontuação é um
componente da ordem final de um registro. A consulta combina isso com outros
indicadores, como a novidade que modula a pontuação de atualidade.
Na implementação atual, a parte do IDF do TF/IDF só está disponível quando
enhance_query=>true
é usada. Ele calcula a frequência relativa das palavras
com base no corpus da Web completo usado pela Pesquisa Google, em vez de um
índice de pesquisa específico. Se a melhoria de consulta não estiver ativada, a pontuação só
usará o componente de frequência de termo (TF, na sigla em inglês). Ou seja, o termo IDF é definido como 1.
A função SCORE
retorna valores que servem como pontuações de relevância que
o Spanner usa para estabelecer uma ordem de classificação. Eles não têm significado
independente. Quanto maior a pontuação, melhor a correspondência com a consulta.
Normalmente, argumentos como query
e enhance_query
são iguais nas funções
SEARCH
e SCORE
para garantir a consistência na recuperação e na classificação.
A maneira recomendada de fazer isso é usar esses argumentos com
parâmetros de consulta
em vez de literais de string e especificar os mesmos parâmetros de consulta nas
funções SEARCH
e SCORE
.
Pontuar várias colunas
O Spanner usa a função SCORE
para pontuar cada campo
individualmente. A consulta combina essas pontuações individuais. Uma maneira comum
de fazer isso é somar as pontuações individuais e, em seguida, aumentá-las
de acordo com os pesos de campo fornecidos pelo usuário (que são fornecidos usando parâmetros de consulta
SQL).
Por exemplo, a consulta a seguir combina a saída de duas funções 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
Este exemplo usa os parâmetros de consulta $1
e $2
, que são vinculados a "quinta sinfonia" e "nota azul", respectivamente.
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
O exemplo a seguir adiciona dois parâmetros de aumento:
- A atualização (
FreshnessBoost
) aumenta a pontuação com(1 + @freshnessweight * GREATEST(0, 30 - DaysOld) / 30)
- A popularidade(
PopularityBoost
) aumenta a pontuação multiplicando-a pelo fator(1 + IF(HasGrammy, @grammyweight, 0)
.
Para facilitar a leitura, a consulta usa o operador 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
Este exemplo usa os parâmetros de consulta $1
, $2
, $3
, $4
, $5
e $6
,
que são vinculados aos valores especificados para titlequery
, studioquery
,
titleweight
, studioweight
, grammyweight
e freshnessweight
,
respectivamente.
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
também pode ser usado na pesquisa e na pontuação para simplificar as consultas quando
apropriado.
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
Este exemplo usa
spanner.tokenlist_concat
.
O parâmetro de consulta $1
está vinculado a "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
Otimizar correspondências de ordenação de consultas
O Spanner aplica um aumento multiplicativo na saída da função SCORE
para valores que contêm os termos da consulta na mesma ordem em que aparecem na consulta. Há duas versões desse aumento: correspondência parcial e exata. Um aumento de correspondência parcial é aplicado quando:
- O
TOKENLIST
contém todos os termos originais da consulta. - Os tokens estão adjacentes uns aos outros e na mesma ordem em que aparecem na consulta.
Há algumas regras especiais para conjunções, negações e frases:
- Uma consulta com uma negação não pode receber um aumento de correspondência parcial.
- Uma consulta com uma conjunção recebe um aumento se parte dela aparecer nos locais adequados.
- Uma consulta com uma frase recebe um aumento se a frase aparecer no
TOKENLIST
e o termo à esquerda da frase na consulta aparecer à esquerda da frase noTOKENLIST
. O mesmo se aplica ao termo à direita da frase.
O Spanner aplica um aumento de correspondência exata quando todas as regras anteriores são verdadeiras e o primeiro e o último token na consulta são o primeiro e o último token no documento.
Documento de exemplo: Bridge Over Troubled Water
Consulta | Aprimoramento aplicado |
---|---|
Bridge Troubled | sem aumento |
Ponte sobre água | sem aumento |
Ponte (sobre ou com problemas) de água | sem aumento |
Bridge Over | aumento parcial |
Bridge Over (Troubled OR Water) | aumento parcial |
Bridge Over Troubled Water | aumento exato |
Ponte "Over Troubled" Water | aumento exato |
Ponte ("Over Troubled" OR missingterm) Água | aumento exato |
Limitar a profundidade de recuperação
Os índices de pesquisa geralmente contêm milhões de documentos. Para consultas em que os predicados têm baixa seletividade, não é prático classificar todos os resultados. As consultas de pontuação geralmente têm dois limites:
- Limite de profundidade de recuperação: o número máximo de linhas a serem pontuadas.
- Limite de tamanho do conjunto de resultados: o número máximo de linhas que a consulta precisa retornar (geralmente o tamanho da página).
As consultas podem limitar a profundidade de recuperação com subconsultas 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
Este exemplo usa os parâmetros de consulta $1
, $2
e $3
, que são vinculados aos valores especificados para title_query
, retrieval_limit
e page_size
, respectivamente.
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
Isso funciona muito bem se o Spanner usa o indicador de classificação mais importante para classificar o índice.
A seguir
- Saiba mais sobre consultas de pesquisa de texto completo.
- Saiba como realizar uma pesquisa de substring.
- Saiba como paginar os resultados da pesquisa.
- Saiba como combinar consultas de texto completo e não de texto.
- Saiba como pesquisar várias colunas.