Full-Text Search no PostgreSQL

Stemming, lexemas e tesauro

Redução morfológica, plural/singular e sinônimos configuráveis no PostgreSQL.

Intermediário 45 min 34 pontos Leitura 0%

Nesta aula você vai

  • Explicar stemming e lexemas na configuração portuguese
  • Configurar sinônimos via dicionário/tesauro do PostgreSQL
  • Validar com ts_debug se plural, singular e sinônimos colapsam como esperado

Stemming, lexemas e tesauro

Objetivos

Nesta aula você vai:

  • Ver como o stemming português reduz flexões a lexemas
  • Introduzir sinônimos de domínio (tesauro) para catálogo e tickets
  • Testar o analisador com ts_debug antes de promover a configuração

Introdução

Usuários não digitam o texto canônico do banco. Buscam furadeiras, furadeira ou parafusadeira de impacto quando o anúncio diz furadeira de impacto. Stemming trata morfologia; tesauro/sinônimos tratam vocabulário de negócio. Ambos vivem na configuração de texto do PostgreSQL — não em OR manuais no SQL da aplicação.

No OficinaHub, “chave de fenda” e “chave fenda” precisam se encontrar; no TicketFlow, “cobrança” e “faturamento” podem ser sinônimos operacionais da fila financeira.

Conteúdo

Stemming e lexemas

Com 'portuguese', o stemmer reduz formas flexionadas:

SELECT to_tsvector('portuguese', 'furadeiras elétricas'),
       to_tsvector('portuguese', 'furadeira elétrica');

Na prática, os lexemas tendem a coincidir o suficiente para @@ casar singular/plural na maioria dos casos. Não é lematização linguística perfeita: é heurística útil.

SELECT * FROM ts_debug('portuguese', 'ferramentas manuais usadas');

Observe as colunas alias, description, token, dictionaries, lexemes. Você verá stopwords removidas e stems emitidos.

Limites do stemmer

Caso Comportamento típico Estratégia
Plural regular Costuma colapsar Confiar no portuguese
Estrangeirismos Pode falhar Sinônimo ou simple em campo separado
Siglas / SKUs Não devem stemmar Campo literal + B-tree
Nomes próprios Risco de overstemming Dicionário específico / sem stemming

Tesauro (sinônimos)

O PostgreSQL permite dicionários de sinônimos e tesauros instalados no diretório de configuração de texto ($SHAREDIR/tsearch_data). Fluxo conceitual:

  1. Criar arquivo de regras (ex.: oficina_syn.syn ou tesauro .ths)
  2. Registrar dicionário CREATE TEXT SEARCH DICTIONARY
  3. Montar uma configuração que use esse dicionário na cadeia
  4. Reindexar search_vector / GIN com a nova config

Exemplo ilustrativo de sinônimos de domínio (conteúdo do arquivo de sinônimos):

parafusadeira furadeira
multimetro multímetro
torquimetro torquímetro

Uso após a configuração customizada (nome hipotético portuguese_oficina):

SELECT to_tsvector('portuguese_oficina', 'parafusadeira de impacto 18V');
SELECT plainto_tsquery('portuguese_oficina', 'furadeira impacto');

Se o dicionário expandir sinônimos corretamente, a consulta por furadeira encontra documentos que só citam parafusadeira (conforme a política escolhida: expansão no índice, na query, ou ambos — defina com o DBA).

Aplicação prática no TicketFlow

-- Configuração de busca alinhada ao domínio
-- (após criar portuguese_suporte com sinônimos cobrança/faturamento)
UPDATE tickets
SET search_vector =
  to_tsvector(
    'portuguese_suporte',
    coalesce(assunto, '') || ' ' || coalesce(corpo, '')
  );
-- Com coluna GENERATED, altere a expressão gerada e reconstrua

Sempre que a regconfig muda, reconstrua vetores e índices.

Problema comum e solução

Problema: sinônimos definidos só na aplicação (REPLACE de termos antes do SQL) divergem entre serviços e esquecem stemming.

Solução: centralize morfologia e sinônimos na configuração de FTS do PostgreSQL (ou num único microserviço de análise). A aplicação envia o texto cru do usuário; o banco analisa com a regconfig versionada.

Como analisar

-- Mesmos lexemas?
SELECT to_tsvector('portuguese', 'serras circulares')
    @@ plainto_tsquery('portuguese', 'serra circular');

-- Debug fino
SELECT * FROM ts_debug('portuguese', 'serras circulares');
SELECT * FROM ts_debug('portuguese', 'serra circular');

-- Após tesauro customizado
SELECT * FROM ts_debug('portuguese_oficina', 'parafusadeira');

Monte testes automatizados de regressão: lista de pares (consulta → id esperado) rodando contra um conjunto de dados semente.

Resumo

  • Stemming reduz flexões a lexemas; portuguese cobre o caso geral
  • Tesauro/sinônimos capturam vocabulário de negócio que stemming não resolve
  • Mude regconfig → reconstrua tsvector e GIN
  • ts_debug é a lupa obrigatória antes de promover configuração nova