Como Fazer Buscas Sem Acento no PostgreSQL com Laravel

Published on 12 abril, 2025 by Raimundo CF IT

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.

SQL
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:

SQL
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:

PHP
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.

Busca sem acento PostgreSQL com Laravel

Leave a Reply

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *