Fundamentos de Full-Text Search
Tokenização e stopwords
Como o texto vira tokens e por que preposições e artigos são descartados.
Nesta aula você vai
- Descrever as etapas de tokenização em um motor full-text
- Explicar o papel das stopwords e o risco de removê-las demais
- Aplicar to_tsvector e equivalentes mentais ao MySQL FULLTEXT
Tokenização e stopwords
Objetivos
Nesta aula você vai:
- Percorrer o pipeline que transforma texto bruto em tokens indexáveis
- Entender por que artigos e preposições costumam ser descartados
- Experimentar tokenização em português com exemplos de catálogo e tickets
Introdução
Full-text search começa antes do índice: começa na análise léxica. Sem essa etapa, o motor armazenaria strings inteiras e voltaria ao mundo do LIKE. Tokenizar é decidir onde uma palavra começa e termina, como normalizar acentos/caixa e o que jogar fora porque não discrimina documentos.
Voltemos à Estante Norte. A sinopse “O guia prático de redes neurais para o time de dados” contém palavras de conteúdo (guia, prático, redes, neurais, time, dados) e palavras funcionais (o, de, para). Se indexássemos tudo com o mesmo peso, consultas como de inundariam o índice e o ranking perderia sinal.
Conteúdo
Pipeline típico
- Segmentação: cortar o texto em candidatos a token (espaços, pontuação)
- Normalização: minúsculas, às vezes remoção de acentos conforme configuração
- Stopwords: remover termos muito frequentes e pouco discriminativos
- Stemming / lemmatização (opcional): reduzir flexões a um radical ou lema
- Emissão: gravar tokens (com posições) no índice invertido
-- PostgreSQL: ver o resultado da análise
SELECT to_tsvector(
'portuguese',
'O guia prático de redes neurais para o time de dados'
);
Resultado ilustrativo:
'dad':9 'gui':2 'neural':6 'pratic':3 'red':5 'tim':8
| Etapa | Efeito no exemplo |
|---|---|
| Segmentação | Separa palavras e ignora pontuação residual |
Stopwords portuguese |
Remove o, de, para |
| Stemming | prático → pratic, redes → red, etc. |
Stopwords: sinal versus ruído
Stopwords existem porque termos ubíquos aparecem em quase todos os documentos. Indexá-los:
- Infla o índice (postings longuíssimos)
- Empobrece o ranking (tudo “casa” com
de) - Aumenta o custo de consulta composta
Há exceções. Em catálogos de código ou SKU, a, in, or podem ser significativos. Em português literário, remover agressivamente demais pode prejudicar títulos curtos. A lista padrão do idioma é um bom ponto de partida; customizar exige evidência de busca real.
-- TicketFlow: corpo de ticket com muito “ruído” funcional
SELECT to_tsvector(
'portuguese',
'O cliente relatou que o gateway de pagamento retornou timeout após a confirmação'
);
Termos de conteúdo (cliente, gateway, pagamento, retornou, timeout, confirmação) tendem a permanecer; artigos e preposições caem.
MySQL: a intuição correspondente
No MySQL FULLTEXT, a análise também tokeniza e aplica stopwords (lista do servidor / plugin). O modo NATURAL LANGUAGE e o BOOLEAN operam sobre tokens, não sobre substrings:
-- Conceito: MATCH usa o analisador FULLTEXT da tabela
SELECT id, titulo
FROM obras
WHERE MATCH(titulo, sinopse) AGAINST ('redes neurais' IN NATURAL LANGUAGE MODE);
Consultas com termos só de stopword podem retornar vazio ou comportamento degenerado — outro motivo para educar o produto a não buscar apenas de ou para.
Tokens e posição
Muitos motores guardam a posição do token no documento. Isso permite:
- Frases (
"rede neural"como sequência) - Ranking que favorece termos no início
- Consultas de proximidade
Sem posições, sobra apenas presença/ausência do termo — útil, mas mais pobre.
Problema comum e solução
Problema: a busca “não acha” títulos compostos só de stopwords ou termos curtos demais (abaixo do ft_min_token_size / configuração equivalente).
Solução: documentar limites do analisador para o time de produto; ajustar listas de stopword e tamanhos mínimos com cuidado; para códigos curtos, manter um campo literal indexado à parte (B-tree / LIKE 'SKU%'), sem exigir do FTS o que ele não foi projetado para resolver.
Como analisar
Sempre inspecione o que o analisador realmente emite:
-- PostgreSQL
SELECT * FROM ts_debug('portuguese', 'ferramentas elétricas para madeira úmida');
-- Comparar consulta e documento
SELECT plainto_tsquery('portuguese', 'ferramenta elétrica madeira');
-- MySQL: valide com consultas controladas e EXPLAIN;
-- confira ft_min_token_size e a stopword list do servidor
SHOW VARIABLES LIKE 'ft_min_token_size';
Se o token que o usuário digita não sobrevive à análise, nenhum índice invertido o encontrará.
Resumo
- Tokenização transforma texto em unidades indexáveis; stopwords removem ruído frequente
- Em português, artigos e preposições costumam sair — e isso é desejável na maioria dos catálogos
- MySQL FULLTEXT e PostgreSQL
tsvectorcompartilham a mesma ideia analítica - Debugar busca começa por ver os tokens, não por adicionar mais
ORno SQL