Como Fazer Buscas Sem Acento no PostgreSQL com Laravel

Neste tutorial, você aprenderá a implementar uma busca sem acento e sem diferenciação entre maiúsculas/minúsculas em um banco de dados PostgreSQL usando Laravel. Isso é especialmente útil para dados com nomes brasileiros que possuem acentuação, como “José” ou “João”. Vamos criar uma função SQL personalizada para normalizar o texto e construir consultas performáticas com uso de índices.
Por que o `unaccent()` do PostgreSQL às vezes falha
A extensão nativa unaccent
do PostgreSQL é útil para remover acentos durante buscas. No entanto, em muitos serviços PostgreSQL gerenciados (como Neon, Laravel Cloud ou Supabase), a função unaccent(text)
pode não estar disponível — mesmo quando a extensão aparece como instalada.
Passo 1: Criar uma Função Alternativa Manual
Vamos criar uma função simples usando translate()
para remover acentos manualmente. Ela funciona em qualquer ambiente PostgreSQL.
DROP FUNCTION IF EXISTS public.unaccent_lower;
CREATE OR REPLACE FUNCTION public.unaccent_lower(input text)
RETURNS text AS $$
BEGIN
RETURN lower(
translate(input,
‘ÁÀÂÃÄÅÆÇÉÈÊËÍÌÎÏÑÓÒÔÕÖØÚÙÛÜÝáàâãäåæçéèêëíìîïñóòôõöøúùûüýÿ’,
‘AAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaaceeeeiiiinoooooouuuuyy’)
);
END;
$$ LANGUAGE plpgsql IMMUTABLE;
Passo 2: Criar Índices Sem Acento
Para melhorar o desempenho, recomendamos criar índices funcionais usando nossa nova função:
CREATE INDEX idx_citizens_name_unaccent_lower ON citizens (public.unaccent_lower(name));
CREATE INDEX idx_citizens_cpf_unaccent_lower ON citizens (public.unaccent_lower(cpf));
CREATE INDEX idx_citizens_cns_unaccent_lower ON citizens (public.unaccent_lower(cns));
CREATE INDEX idx_citizens_name_mother_unaccent_lower ON citizens (public.unaccent_lower(name_mother));
Passo 3: Implementar a Busca no Laravel
Agora que o banco está pronto, veja como aplicar a lógica de busca em um componente Livewire ou controller no Laravel:
public function searchCitizen()
{
$term = “%{$this->search}%”;
$motherTerm = “%{$this->searchMother}%”;
$this->result = Citizen::query()
->where(function ($query) use ($term, $motherTerm) {
$query->where(function ($q) use ($term) {
$q->whereRaw(‘public.unaccent_lower(name) LIKE public.unaccent_lower(?)’, [$term])
->orWhereRaw(‘public.unaccent_lower(cpf) LIKE public.unaccent_lower(?)’, [$term])
->orWhereRaw(‘public.unaccent_lower(cns) LIKE public.unaccent_lower(?)’, [$term]);
});
if (!empty($this->searchMother)) {
$query->whereRaw(‘public.unaccent_lower(name_mother) LIKE public.unaccent_lower(?)’, [$motherTerm]);
}
})
->limit(10)
->get();
}
Vantagens Desta Abordagem
- Compatível com qualquer ambiente PostgreSQL (incluindo nuvem e servidores gerenciados)
- Sem dependência de funções
unaccent(text)
indisponíveis - Funciona com nomes, CPFs e CNS sem precisar de full-text search
- Melhora a experiência do usuário com buscas ignorando acentuação
Conclusão
Mesmo que seu provedor PostgreSQL restrinja o uso do unaccent
nativo, você pode implementar sua própria solução com translate()
. Essa técnica simples garante que seu app Laravel ofereça uma busca eficiente e confiável — mesmo com variações de acentos nos dados dos usuários.
