Limites da busca com LIKE
Relevância versus busca por substring
Como wildcards confundem tokens de idioma com sequências de caracteres e geram falsos positivos.
Nesta aula você vai
- Explicar a diferença entre token linguístico e sequência de caracteres
- Identificar falsos positivos típicos gerados por LIKE com curingas
- Relacionar relevância com campos, frequência e intenção do usuário
Relevância versus busca por substring
Objetivos
Nesta aula você vai:
- Separar token (unidade de idioma) de substring (fatia de caracteres)
- Mapear falsos positivos e falsos negativos causados por curingas
- Definir relevância como critério de ordenação, não como “bateu ou não bateu”
Introdução
Linguagem natural não é uma fita contínua de bytes. Em português, “ferramentas”, “ferramenta” e “a ferramenta elétrica” compartilham uma ideia; a sequência menta aparece em “ferramenta” e também em “fundamenta” e “comentário”. Busca por substring trata o texto como corda; busca por relevância trata o texto como documento com termos.
No OficinaHub, um marketplace B2B de ferramentas manuais e elétricas, o comprador digita serra. Com LIKE '%serra%', o sistema pode trazer “asserra de madeira” (se o catálogo tiver o termo), “conservação de serra” em um FAQ colado na descrição, e até SKUs cujo código interno contém SERRA por acaso. Ao mesmo tempo, pode deixar de lado “serras circulares” se a consulta for serra circular e a sinopse usar outra ordem de palavras.
Conteúdo
Substring: o motor vê caracteres
-- OficinaHub: predicado por substring
SELECT sku, nome, categoria
FROM produtos
WHERE nome LIKE '%serra%'
OR descricao LIKE '%serra%';
O predicado é verdadeiro sempre que a sequência s-e-r-r-a aparece. Não há noção de limite de palavra. Em muitos collations, maiúsculas e minúsculas se igualam; ainda assim, morfologia (plural, gênero, derivados) continua fora do jogo.
| Consulta | Pode casar indevidamente | Pode falhar em casar |
|---|---|---|
%para% |
“preparação”, “paradoxo” (dependendo do texto) | “pára” com acentuação diferente |
%sol% |
“consolador”, “absoluto” | “sóis” / “solares” |
%kit% |
“marketing”, “packet” em importações EN | “kits” se stemming não existir |
Token: o motor vê palavras (depois de normalizar)
Full-text primeiro tokeniza: corta o texto em unidades, normaliza caixa, descarta stopwords e, em motores com stemming, reduz formas flexionadas a um lexema. A consulta serra circular vira um conjunto de termos com operadores, não uma fatia rígida de caracteres.
-- Ilustração conceitual (PostgreSQL): tokens, não substrings
SELECT to_tsvector('portuguese', 'Serra circular de 7 polegadas para madeira úmida');
-- resultado típico: 'circular':2 'madeir':6 'poleg':4 'serr':1 'umid':7
Observe que preposições e artigos somem, e “madeira”/“úmida” podem virar radicais. Isso é o oposto de LIKE, que exige a sequência literal (salvo collation).
Relevância não é booleana
Substring responde sim/não. Relevância responde “quanto este documento importa para esta consulta?”. Em um ranking simples:
- Ocorrência no nome vale mais que na descrição
- Termos raros no catálogo pesam mais que termos ubíquos
- Documentos curtos e focados podem superar paredes de texto genérico
-- LIKE não tem score nativo; a aplicação improvisaria algo frágil
SELECT sku, nome,
CASE
WHEN nome LIKE '%serra circular%' THEN 3
WHEN nome LIKE '%serra%' THEN 2
WHEN descricao LIKE '%serra%' THEN 1
ELSE 0
END AS score_improvisado
FROM produtos
WHERE nome LIKE '%serra%' OR descricao LIKE '%serra%'
ORDER BY score_improvisado DESC;
Esse CASE é um ranking de brinquedo: não entende sinônimos, não normaliza morfologia e multiplica a quantidade de predicados LIKE. Em escala, vira dívida técnica.
Problema comum e solução
Problema: o time adiciona mais OR e CASE para “melhorar relevância” em cima de LIKE, e a consulta fica ilegível, lenta e ainda cheia de falsos positivos.
Solução: modelar a busca como recuperação de documentos — índice invertido + ranking do motor — e usar substring só quando o requisito for literalmente “contém este código/trecho exato”.
Como analisar
Monte um conjunto de consultas de regressão qualitativa (dez a quinze buscas reais do suporte) e compare:
-- Amostra de falsos positivos por substring curta
SELECT sku, nome
FROM produtos
WHERE nome LIKE '%kit%'
AND nome NOT ILIKE '%kit %'
AND nome NOT ILIKE 'kit%'
LIMIT 30;
Se a lista estiver cheia de nomes que só “passam por cima” da sequência, você tem prova de que substring ≠ relevância. Guarde esses casos para validar a migração para full-text.
Resumo
- Substring opera em caracteres; relevância opera em tokens e pontuação
- Curingas geram falsos positivos (
soldentro de outras palavras) e falsos negativos (flexões, ordem de termos) - Improvisar score com
CASE+LIKEmascara o problema e piora o SQL - Full-text existe precisamente para alinhar o motor à linguagem do usuário