Categorias
Desenvolvimento Web Tutoriais

Fulltext Search – Busca Textual com Postgres – Parte 1

O que é busca textual e qual a vantagem?

Hoje em dia qualquer aplicação precisa de uma interface de busca, mas ainda é muito comum achar sistemas que dependem de uma entrada do usuário quase perfeita para conseguir encontrar um resultado. Internamente, essas aplicações usam e abusam de operadores SQL como LIKE e ILIKE , por vezes contando com a ajuda do coringa %% para encontrar palavras ou expressões que contém a expressão pesquisada (uma substring em outras palavras).

Mas qual a diferença de usar um simples LIKE e uma busca textual? A diferença começa pelo fato de um índice de busca textual armazenar os dados depois de um pré-processamento. Esse pré-processamento costuma envolver uma normalização (tudo em caixa baixa, por exemplo), identificação de tokens (pedaços lógicos do texto) e descarte daquilo que não possui valor semântico (remove artigos e preposições que costumam aparecer muito sem ter valor real pra quem pesquisa, por exemplo), transformação das palavras encontradas em seus radicais básicos (processo chamado de stemming) e as vezes até incluindo ou substituindo essas palavras por sinônimos. Parece complicado né? E é, mas você não precisa ser um pesquisador em NLP (processamento de linguagem natural) pra ter uma busca textual simples.

Em termos práticos, o que você ganha com uma busca textual?

Considere uma tabela chamada artigos e nela uma coluna conteudo do tipo TEXT. É um cenário comum onde se usa o operador LIKE. Agora vamos colocar uma segunda coluna conteudo_fulltext, essa do tipo TSVECTOR, que é um tipo próprio para busca textual.

Dentre os artigos salvos nessa tabela, temos um com o seguinte parágrafo:

Algumas das principais razões da evasão escolar no Brasil atual são a pobreza, a dificuldade de acesso à escola, a necessidade de trabalho e, principalmente, o desinteresse pelos estudos. Segundo o Programa das Nações Unidas para o Desenvolvimento (PNUD), o país tem a terceira maior taxa de abandono escolar (24,3%) entre os 100 países com maior IDH (Índice de Desenvolvimento Humano), só atrás da Bósnia e Herzegovina (26,8%) e das ilhas de São Cristovão e Névis, no Caribe (26,5%). Na América Latina, só é superado pela Guatemala (35,2%) e pela Nicarágua (51,6%), não tendo sido divulgado o índice do Haiti.

Wikipedia

Imagine que alguém queira encontrar esse parágrafo na busca da nossa aplicação. Esse alguém pesquisa: “evasão escolar do brasil”.

Como isso seria tratado usando apenas um LIKE:

SELECT conteudo FROM artigos WHERE conteudo ILIKE '%evasão escolar do brasil%';

E nosso alguém ficaria frustrado, sem nenhum resultado. Porque ele incluiu a preposição do que não faz parte do trecho contido no parágrafo (nele temos um no).

Agora, se nosso conteúdo está indexado para busca textual, a mesma consulta viraria:

SELECT conteudo FROM artigos WHERE conteudo_fts @@ to_tsquery('evasão escolar do brasil');

E nesse caso, o alguém ficaria feliz com o resultado.

Talvez você esteja perguntando “por que ele não usa Elasticsearch/Sphinx?”. A pergunta é justa e a resposta tão quanto: pra não complicar antes de precisar complicar. Ambos os projetos são excelentes e oferecem recursos avançados/otimizados para busca textual. Mas se sua aplicação já utiliza Postgres e você não tem bilhões de registros para indexar, não existe razão para otimizar prematuramente.

Vale mencionar ainda que em 2019 o Ifood apresentou sua migração da busca do aplicativo para usar esse mesmo mecanismo.

Agora que a gente viu uma vantagem em usar busca textual, precisamos aprender como realmente usar.

Mas vou deixar isso para o próximo artigo porque está ficando muito longo.

Antes de finalizar, só quero deixar aqui que o objetivo é ter mais 2 partes nessa sequência de posts. No último vou explicar como utilizar (ou usar como inspiração) um plugin que desenvolvi para CakePHP que adiciona ao framework suporte a busca textual do Postgres: o Autopage\PgSearch.

Atualizado em 19/10/2021: aplicada a correção na query de exemplo conforme o apontamento feito pelo JC Bombardelli nos comentários. Muito obrigado.

Por Cauan Cabral

Desenvolvedor com 2 dígitos de experiências, especialista em PHP e CakePHP mas com bagagens em JavaEE, Node.js, Javascript (ES6, jQuery, Angular) e Python. Interessado em automação, Machine Learning e cozinha.

5 respostas em “Fulltext Search – Busca Textual com Postgres – Parte 1”

Oi, no seu artigo tem a seguinte instrução para consulta “`SELECT conteudo FROM artigos WHERE conteudo_fts @@ to_tsvector(‘evasão escolar do brasil’);“`

Mas acho que o correto seria to_tsquery, certo ?

Deixe um comentário

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

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.