Full-Text Search no PostgreSQL
Stemming, lexemas e tesauro
Redução morfológica, plural/singular e sinônimos configuráveis no PostgreSQL.
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_debugantes 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:
- Criar arquivo de regras (ex.:
oficina_syn.synou tesauro.ths) - Registrar dicionário
CREATE TEXT SEARCH DICTIONARY - Montar uma configuração que use esse dicionário na cadeia
- 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;
portuguesecobre o caso geral - Tesauro/sinônimos capturam vocabulário de negócio que stemming não resolve
- Mude regconfig → reconstrua
tsvectore GIN ts_debugé a lupa obrigatória antes de promover configuração nova