Nesta página, descrevemos como classificar os resultados da pesquisa para pesquisas de texto completo no Spanner.
O Spanner oferece suporte ao cálculo de uma pontuação de relevância, 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 de 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
Atribuir pontuação aos 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 na frequência de termo–frequência inversa de documento (TF/IDF). A pontuação é um componente da ordenação final de um registro. A consulta combina isso com outros indicadores, como a atualização que modula a pontuação de relevância.
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 das palavras com base no corpus completo da Web usado pela Pesquisa Google, e não em um índice de pesquisa específico. Se o refinamento de rquery não estiver ativado, a pontuação usará apenas o componente de frequência do termo (TF), 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. Elas não têm um 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 no ranking.
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 aumentar de acordo com as ponderações de campo fornecidas pelo usuário (que são fornecidas 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 estão vinculados a "quinta sinfonia" e "blue note", 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 reforço:
- 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
Aumentar as 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 da consulta. - Os tokens são adjacentes 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 dela aparecer nos locais apropriados.
- Uma consulta com uma frase recebe uma otimização 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 tokens inicial e final na consulta são os mesmos no documento.
Exemplo de documento: Bridge Over Troubled Water
| Consulta | Bônus aplicado |
|---|---|
| Bridge Troubled | sem bônus |
| Ponte sobre outro tipo de água | sem bônus |
| Bridge (Over OR Troubled) Water | sem bônus |
| Ponte sobre | reforço parcial |
| Bridge Over (Troubled OR Water) | reforço parcial |
| Bridge Over Troubled Water | bônus exato |
| Ponte "Over Troubled" Water | bônus exato |
| Ponte ("Over Troubled" OR missingterm) Water | bônus exato |
Limitar a profundidade da 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 deve retornar (normalmente o tamanho da página).
As consultas podem limitar a profundidade da 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 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 combinar consultas de texto completo e não textuais.
- Saiba como pesquisar em várias colunas.