Fix searching in mysql. It now does one query for all tokens. And person_spec is green!

This commit is contained in:
Sarah Mei 2010-12-22 22:24:04 -08:00
parent 924bcca0e2
commit 2b7eeffd5b
3 changed files with 54 additions and 39 deletions

View file

@ -39,18 +39,24 @@ class Person < ActiveRecord::Base
def self.search(query) def self.search(query)
return [] if query.to_s.empty? return [] if query.to_s.empty?
query_tokens = query.to_s.strip.split(" ")
p = []
query_tokens.each do |raw_token| where_clause = <<-SQL
profiles.first_name LIKE ? OR
profiles.last_name LIKE ? OR
people.diaspora_handle LIKE ?
SQL
sql = ""
tokens = []
query_tokens = query.to_s.strip.split(" ")
query_tokens.each_with_index do |raw_token, i|
token = "%#{raw_token}%" token = "%#{raw_token}%"
p = Person.searchable.where('profiles.first_name LIKE :token', :token => token).limit(30) \ sql << " OR " unless i == 0
| Person.searchable.where('profiles.last_name LIKE :token', :token => token).limit(30) \ sql << where_clause
| Person.searchable.where('profiles.diaspora_handle LIKE :token', :token => token).limit(30) \ tokens.concat([token, token, token])
| p
end end
return p Person.searchable.where(sql, *tokens).order("profiles.first_name")
end end
def name def name

View file

@ -24,6 +24,12 @@ Factory.define :person do |p|
p.serialized_public_key OpenSSL::PKey::RSA.generate(1024).public_key.export p.serialized_public_key OpenSSL::PKey::RSA.generate(1024).public_key.export
end end
Factory.define :searchable_person, :parent => :person do |p|
p.after_build do |person|
person.profile.searchable = true
end
end
Factory.define :user do |u| Factory.define :user do |u|
u.sequence(:username) { |n| "bob#{n}#{r_str}" } u.sequence(:username) { |n| "bob#{n}#{r_str}" }
u.sequence(:email) { |n| "bob#{n}#{r_str}@pivotallabs.com" } u.sequence(:email) { |n| "bob#{n}#{r_str}@pivotallabs.com" }

View file

@ -140,56 +140,57 @@ describe Person do
describe '.search' do describe '.search' do
before do before do
@connected_person_one = Factory.create(:person) Person.delete_all
@connected_person_two = Factory.create(:person) @robert_grimm = Factory.create(:searchable_person)
@connected_person_three = Factory.create(:person) @eugene_weinstein = Factory.create(:searchable_person)
@connected_person_four = Factory.create(:person) @yevgeniy_dodis = Factory.create(:searchable_person)
@casey_grippi = Factory.create(:searchable_person)
@connected_person_one.profile.first_name = "Robert" @robert_grimm.profile.first_name = "Robert"
@connected_person_one.profile.last_name = "Grimm" @robert_grimm.profile.last_name = "Grimm"
@connected_person_one.profile.save @robert_grimm.profile.save
@robert_grimm.reload
@connected_person_two.profile.first_name = "Eugene" @eugene_weinstein.profile.first_name = "Eugene"
@connected_person_two.profile.last_name = "Weinstein" @eugene_weinstein.profile.last_name = "Weinstein"
@connected_person_two.save @eugene_weinstein.profile.save
@eugene_weinstein.reload
@connected_person_three.profile.first_name = "Yevgeniy" @yevgeniy_dodis.profile.first_name = "Yevgeniy"
@connected_person_three.profile.last_name = "Dodis" @yevgeniy_dodis.profile.last_name = "Dodis"
@connected_person_three.save @yevgeniy_dodis.profile.save
@yevgeniy_dodis.reload
@connected_person_four.profile.first_name = "Casey" @casey_grippi.profile.first_name = "Casey"
@connected_person_four.profile.last_name = "Grippi" @casey_grippi.profile.last_name = "Grippi"
@connected_person_four.save @casey_grippi.profile.save
@casey_grippi.reload
end end
it 'should return nothing on an emprty query' do it 'should return nothing on an empty query' do
people = Person.search("") people = Person.search("")
people.empty?.should be true people.empty?.should be true
end end
it 'should yield search results on partial names' do it 'should yield search results on partial names' do
people = Person.search("Eu") people = Person.search("Eu")
people.include?(@connected_person_two).should == true people.count.should == 1
people.include?(@connected_person_one).should == false people.first.should == @eugene_weinstein
people.include?(@connected_person_three).should == false
people.include?(@connected_person_four).should == false
people = Person.search("wEi") people = Person.search("wEi")
people.include?(@connected_person_two).should == true people.count.should == 1
people.include?(@connected_person_one).should == false people.first.should == @eugene_weinstein
people.include?(@connected_person_three).should == false
people.include?(@connected_person_four).should == false
people = Person.search("gri") people = Person.search("gri")
people.include?(@connected_person_one).should == true people.count.should == 2
people.include?(@connected_person_four).should == true people.first.should == @casey_grippi
people.include?(@connected_person_two).should == false people.second.should == @robert_grimm
people.include?(@connected_person_three).should == false
end end
it 'should yield results on full names' do it 'should yield results on full names' do
people = Person.search("Casey Grippi") people = Person.search("Casey Grippi")
people.should == [@connected_person_four] people.count.should == 1
people.first.should == @casey_grippi
end end
it 'should only display searchable people' do it 'should only display searchable people' do
@ -199,7 +200,9 @@ describe Person do
end end
it 'should search on handles' do it 'should search on handles' do
Person.search(@connected_person_one.diaspora_handle).should include @connected_person_one people = Person.search(@robert_grimm.diaspora_handle)
people.count.should == 1
people.first.should == @robert_grimm
end end
end end