Archive for the ‘Databases’ Category
Insensitivity: O plugin insensível
Consultas case insensitive e independentes de acentos que funcionem em qualquer SGBD são difíceis de conseguir, pois cada banco possui sua maneira específica de fazer isso. Se forem tomados alguns cuidados, é possível usar a sintaxe correta de acordo com o adaptador que estamos usando. No PostgreSQL por exemplo, para conseguir uma consulta case insensitive e independente de acentos, temos que fazer coisas assim ou assim.
O problema em usar conversões nas colunas é que, além delas não fazerem parte padrão SQL, perdemos os índices na coluna, o que vai fazer nossa consulta demorar um pouco mais (dependendo da quatidade de registros, usar ou não um índice pode fazer uma grande diferença). Para resolver esse problema, criei o plugin “Insensitivity“, que usa uma coluna extra para armazenar o valor sem acentos e em minúsculas. Assim, durante as consultas, o ActiveRecord irá utilizar essa coluna em vez da coluna com o valor real.
Vantagens dessa abordagem
Independente de banco
Se hover índices, serão usados
Desvantagens
Utiliza o dobro de espaço.
Instalando e usando o plugin
script/plugin install git://github.com/fernandoluizao/insensitivity.git
No seu model, você deve indicar quais campos usarão a pesquisa case insensitive:
class User < ActiveRecord:Base insensible :name, :email end
Depois, você DEVE adicionar à tabela, os campos com o mesmo nome dos que foram indicados e com o sufixo “_search”. Se desejar, também coloque índices para melhorar a performance. Por exemplo:
script/generate migration add_search_fields
def self.up
change_table :users do |t|
t.string :name_search
t.string :email_search
end
add_index :users, :name_search
add_index :users, :email_search
#Se sua tabela ja tiver dados, vc pode usar
#User.make_insensible!
#Isso vai inicializar os novos campos nos registros já existentes
end
def self.down
change_table :users do |t|
t.remove :name_search
t.remove :email_search
end
end
Para fazer as buscas, não muda nada. Veja as consultas geradas:
User.find_by_name('bla')
SELECT * FROM users WHERE name_search = 'bla'
User.find(:first, :conditions => ['name = ?', 'bla'], :order => 'name') SELECT * FROM users WHERE name_search = 'bla' ORDER BY name LIMIT 1
Tudo funciona de forma transparente, sem vc precisar se preocupar =). Sua única preocupação deve ser passar o valor nas conditions sem acentos e em minusculas, para isso pode usar o método “insensible”, adicionado à classe String:
User.find(:first, :conditions => ['name LIKE ?', "%#{params[:name].insensible}%"])
SELECT * FROM users WHERE name_search LIKE '%bla%'
Bom, é isso, pesquisa sem sentimentos
. Quem quiser colaborar:
http://github.com/fernandoluizao/insensitivity/
PS: Testei apenas com rails 2.2.2. Pode não funcionar com versões mais antigas (< 2.0)
Me recomende