Nesta página, descrevemos como classificar os resultados da pesquisa para pesquisas de texto completo no Spanner.
O Spanner é compatível com o cálculo de uma pontuação de atualidade, que fornece um elemento básico 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
Pontuar termos de consulta com a função SCORE
A função SCORE calcula uma pontuação para cada termo de consulta e, em seguida, combina as pontuações. A
pontuação por termo é baseada aproximadamente na frequência do termo/frequência inversa de documentos
(TF/IDF). A pontuação é um
componente da ordem final de um registro. A consulta o combina com outros
indicadores, como o frescor que modula a pontuação de atualidade.
Na implementação atual, a parte IDF do TF/IDF só está disponível quando
enhance_query=>true é usado. Ele calcula a frequência relativa de palavras
com base no corpus completo da Web usado pela Pesquisa Google, em vez de um
índice da Pesquisa específico. Se a melhoria de rquery não estiver ativada, a pontuação usará apenas
o componente de frequência de termo (TF, na sigla em inglês). Ou seja, o termo IDF será 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 os mesmos 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. Em seguida, 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) OR 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 estão vinculados a
"fifth symphony" e "blue note", respectivamente.
SELECT albumid
FROM albums
WHERE spanner.search(title_tokens, $1) OR 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 otimização:
- 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) OR 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 estã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) OR 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 ordem de consulta
O Spanner aplica um aumento multiplicativo à saída da função SCORE para valores que contêm os termos de consulta na mesma ordem em que aparecem na consulta. Há duas versões desse aumento: correspondência parcial
e correspondência exata. Um aumento de correspondência parcial é aplicado quando:
- O
TOKENLISTcontém todos os termos originais na consulta. - Os tokens são adjacentes uns aos outros e estão 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 da conjunção aparecer nos locais apropriados.
- 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, e 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 os primeiros e últimos tokens na consulta são os primeiros e últimos tokens no documento.
Exemplo de documento: Bridge Over Troubled Water
| Consulta | Otimização aplicada |
|---|---|
| Bridge Troubled | sem boost |
| Ponte sobre outro corpo de água | sem boost |
| Bridge (Over OR Troubled) Water | sem boost |
| Ponte sobre | boost parcial |
| Bridge Over (Troubled OR Water) | boost parcial |
| Bridge Over Troubled Water | boost exato |
| Bridge "Over Troubled" Water | boost exato |
| Bridge ("Over Troubled" OR missingterm) Water | boost exato |
Versões do Scorer
O algoritmo de pontuação é atualizado periodicamente. Cada versão inclui um conjunto de melhorias no algoritmo de pontuação. Para uma lista detalhada das diferenças entre as versões, consulte Versões do Scorer.
É possível definir a versão padrão do pontuador para seu banco de dados ou especificar uma versão para uma consulta específica.
Se você não especificar uma versão do avaliador para seu banco de dados ou consulta, a versão padrão será atualizada automaticamente quando uma versão mais recente for lançada.
Definir a versão padrão do avaliador do banco de dados
É possível definir a versão padrão do algoritmo de pontuação para seu banco de dados. Essa
opção determina qual versão do algoritmo de pontuação
o Spanner usa quando a função SCORE é chamada sem uma
opção de pontuação version explícita.
GoogleSQL
Defina a opção de banco de dados score_version:
ALTER DATABASE database_name SET OPTIONS (score_version = 2)
PostgreSQL
Defina a opção de banco de dados spanner.score_version:
ALTER DATABASE database_name SET "spanner.score_version" = 2
Os valores válidos para a opção de banco de dados são 1 ou 2. Se o parâmetro version
estiver presente em uma solicitação, ele vai substituir a versão padrão do banco de dados.
Substituir a versão do avaliador por consulta
É possível substituir a versão padrão do avaliador para uma consulta específica usando o
parâmetro version no argumento options da função SCORE. Se uma consulta
definir uma versão do pontuador, ela vai substituir a versão padrão do banco de dados.
O exemplo a seguir substitui a versão padrão do avaliador especificando
version no parâmetro options:
GoogleSQL
SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, @query)
ORDER BY SCORE(
AlbumTitle_Tokens,
@query,
options=>JSON '{"version": 2}'
) DESC
PostgreSQL
Este exemplo usa o parâmetro de consulta $1, que está vinculado à string de consulta.
SELECT albumid
FROM albums
WHERE spanner.search(albumtitle_tokens, $1)
ORDER BY spanner.score(
albumtitle_tokens,
$1,
options => '{"version": 2}'::jsonb
) DESC
Limitar a profundidade da recuperação
Os índices da 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 deve retornar (normalmente o tamanho da página).
As consultas podem limitar a profundidade de recuperação com subconsultas SQL:
GoogleSQL
SELECT AlbumId
FROM
(
SELECT AlbumId, SCORE(Title_Tokens, @p1) AS score
FROM Albums
WHERE SEARCH(Title_Tokens, @p1)
ORDER BY ReleaseTimestamp DESC
LIMIT @retrieval_limit
)
ORDER BY score DESC
LIMIT @page_size
PostgreSQL
Este exemplo usa os parâmetros de consulta $1, $2 e $3, que estão vinculados aos valores especificados para title_query, retrieval_limit e page_size, respectivamente.
SELECT albumid
FROM
(
SELECT albumid, spanner.score(title_tokens, $1) AS score
FROM albums
WHERE spanner.search(title_tokens, $1)
ORDER BY releasetimestamp DESC
LIMIT $2
) AS subquery
ORDER BY score DESC
LIMIT $3
Isso funciona muito bem se o Spanner usar o indicador de classificação mais importante para ordenar o índice.
A seguir
- Saiba mais sobre consultas de pesquisa de texto completo.
- Saiba como fazer uma pesquisa de substring.
- Saiba como paginar resultados da pesquisa.
- Saiba como misturar consultas de texto completo e não textuais.
- Saiba como pesquisar várias colunas.