Skip to content
maio 16, 2010 / cassiomarques

Usando SQL puro para criar índices com o Thinking-Sphinx

Tenho usado bastante o Thinking-Sphinx (wrapper em Ruby para usar o ActiveRecord com o Sphinx) para implementar buscas. Esses dias enfrentei um problema diferente: precisava indexar um campo formatado mas permitir busca sem usar a formatação. Mais especificamente, precisava busca CPFs e CNPJs sem formatação, sendo que eles estavam gravados formatados no banco de dados. Exemplo: deveria ser possível encontrar o dono do CPF 111.444.777-35 buscando por 1114447735.

Por padrão, o Thinking-Sphinx vai indexar os valores exatos presentes na coluna em questão e associar o índice a este valor. Mas é possível contornar isso. A definição de indices pelo Thinking-Sphinx permite usar uma forma alternativa para passar os valores a serem indexados, geralmente usando uma query SQL nativa. No meu caso, usei os recursos de expressões regulares do PostgreSQL para remover tudo que não fosse número do meu CPF/CNPJ. A coluna usada no meu banco chama-se “entity_number”

define_index do 
  indexes "regexp_replace(entity_number, E'\[\[\:punct\:\]\]', '', 'g')", :as => :raw_entity_number
  group_by "raw_entity_number"
end

Existem duas “pegadinhas” aqui:

  • Os caracteres especiais da expressão regular precisam ser escapados para que o Sphinx monte a query corretamente. Se você vai ou não precisar fazer isso vai depender da query nativa sendo utilizada.
  • O Sphinx precisa sempre usar GROUP BY para cada campo indexado na query que ele envia ao banco para indexar os valores. Por padrão, campos criados como mostrado acima não são incluídos na cláusula GROUP BY e por isso sua indexação vai falhar. Por isso agrupamos explicitamente os resultados usando “group_by :raw_entity_number”. Nosso novo campo será concatenado ao final da query, sem bagunçar os demais valores já presentes na query.

2 Comentários

Deixe um comentário
  1. pat / maio 17 2010 12:22 pm

    Hi Cássio – Great to see you’ve worked out a solution (even though I had to use Google Translate to understand :)

    One thing to note: you don’t need :type for fields – they will always be treated as strings. :type is only useful for attributes.

    Cheers

    • cassiomarques / maio 17 2010 3:37 pm

      Hi Pat, thanks for the tip, I’ll update the post and my code :)

      Thanks!

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: