Fundamentos de Full-Text Search

Ranking de relevância

Como o motor ordena resultados (frequência, posição, campos) e o que isso muda na UX.

Intermediário 42 min 33 pontos Leitura 0%

Nesta aula você vai

  • Identificar sinais clássicos de ranking (TF, raridade, campo, posição)
  • Explicar o impacto do ranking na experiência de busca
  • Preparar o terreno para pesos e ts_rank / score do MATCH

Ranking de relevância

Objetivos

Nesta aula você vai:

  • Nomear os sinais que um motor usa para ordenar documentos candidatos
  • Ligar ranking técnico a decisões de UX (o que aparece no topo)
  • Antecipar APIs de score no MySQL (MATCH) e no PostgreSQL (ts_rank)

Introdução

Encontrar candidatos não basta. Se a caixa de busca do TicketFlow devolve 400 tickets que mencionam timeout, o agente precisa que os mais pertinentes subam: assunto exato, ticket recente com o mesmo gateway, não um comentário antigo enterrado em anexo textual. Ranking é a ponte entre “casou o termo” e “merece a primeira tela”.

Conteúdo

Sinais clássicos (visão de engenharia)

Sinal Ideia Efeito prático
Frequência no documento (TF) Termo aparece várias vezes Documento focado no tema sobe
Raridade no corpus (IDF) Termo raro discrimina mais gatewayX42 pesa mais que erro
Campo / peso Título > corpo > nota interna Assunto bem formulado vence
Posição Termo no início Títulos curtos e diretos ganham
Normalização de comprimento Textos longos não dominam só por repetir Evita “enchimento” de sinopse
Cobertura da consulta Quantos termos da busca aparecem Consultas compostas ficam honestas

Nenhum motor popular expõe todos esses botões da mesma forma, mas a intuição serve para ler a documentação e calibrar pesos.

Score nativo nas consultas

MySQL — score do MATCH:

SELECT id, assunto,
       MATCH(assunto, corpo) AGAINST ('timeout gateway pagamento' IN NATURAL LANGUAGE MODE) AS score
FROM tickets
WHERE MATCH(assunto, corpo) AGAINST ('timeout gateway pagamento' IN NATURAL LANGUAGE MODE)
ORDER BY score DESC
LIMIT 20;

O valor de score é a relevância estimada pelo motor FULLTEXT naquele modo. Use-o na ordenação; não reinventar com CASE + LIKE.

PostgreSQL — ts_rank / ts_rank_cd:

SELECT id, assunto,
       ts_rank(search_vector, query) AS rank
FROM tickets,
     plainto_tsquery('portuguese', 'timeout gateway pagamento') AS query
WHERE search_vector @@ query
ORDER BY rank DESC
LIMIT 20;

ts_rank_cd incorpora densidade/cobertura de forma diferente; teste com o corpus real antes de fixar em produção.

O que muda na UX

  1. Primeira tela honestamente útil: o usuário julga a busca pelos três primeiros itens
  2. Menos reformulação de consulta: ranking bom reduz “vou tentar outra palavra”
  3. Espaço para negócio: depois do score textual, você pode reordenar levemente por frescor, status aberto ou permissão — sem descartar a relevância base
-- TicketFlow: relevância primeiro, depois frescor como desempate
SELECT id, assunto, status, aberto_em,
       ts_rank(search_vector, query) AS rank
FROM tickets,
     plainto_tsquery('portuguese', 'timeout gateway') AS query
WHERE search_vector @@ query
  AND status IN ('aberto', 'em_andamento')
ORDER BY rank DESC, aberto_em DESC
LIMIT 20;

Limites do ranking embutido

Motores SQL não são Elasticsearch/OpenSearch. Não espere aprendizado de máquina de ranking pronto para uso. Para catálogos médios e centrais de atendimento, MATCH/ts_rank com pesos de campo costuma ser suficiente. Se a relevância for o diferencial do produto, avalie um motor dedicado — mas só depois de esgotar o full-text do banco com boa modelagem.

Problema comum e solução

Problema: a API devolve resultados full-text sem ORDER BY de score, e o front exibe na ordem física/PK.

Solução: sempre ordene pelo score/rank (e documente desempates). Relevância sem ordenação é desperdício do índice invertido.

Como analisar

Monte um “golden set”: 15 consultas com o resultado ideal anotado pelo suporte. Compare:

-- Top-5 com rank
SELECT id, assunto, ts_rank(search_vector, q) AS rank
FROM tickets, plainto_tsquery('portuguese', 'cobrança duplicada cartão') AS q
WHERE search_vector @@ q
ORDER BY rank DESC
LIMIT 5;

Se o item esperado não estiver no top-5, ajuste pesos de campo, dicionário de sinônimos ou a própria qualidade dos textos indexados — não volte para LIKE.

Resumo

  • Ranking transforma conjunto candidato em lista útil
  • Sinais típicos: frequência, raridade, campo, posição, comprimento
  • MySQL expõe score via MATCH; PostgreSQL via ts_rank/ts_rank_cd
  • UX de busca se julga pelo topo da lista — ordene pelo score