optimized people search
This commit is contained in:
parent
5e39368414
commit
f560321626
6 changed files with 53 additions and 26 deletions
|
|
@ -47,39 +47,25 @@ class Person < ActiveRecord::Base
|
|||
def self.search_query_string(query)
|
||||
if postgres?
|
||||
where_clause = <<-SQL
|
||||
profiles.first_name ILIKE ? OR
|
||||
profiles.last_name ILIKE ? OR
|
||||
people.diaspora_handle ILIKE ?
|
||||
profiles.full_name ILIKE ? OR
|
||||
profiles.diaspora_handle ILIKE ?
|
||||
SQL
|
||||
else
|
||||
where_clause = <<-SQL
|
||||
profiles.first_name LIKE ? OR
|
||||
profiles.last_name LIKE ? OR
|
||||
people.diaspora_handle LIKE ? OR
|
||||
profiles.first_name LIKE ? OR
|
||||
profiles.last_name LIKE ?
|
||||
profiles.full_name LIKE ? OR
|
||||
people.diaspora_handle LIKE ?
|
||||
SQL
|
||||
end
|
||||
|
||||
sql = ""
|
||||
tokens = []
|
||||
|
||||
query_tokens = query.to_s.strip.split(" ")
|
||||
query_tokens.each_with_index do |raw_token, i|
|
||||
token = "#{raw_token}%"
|
||||
up_token = "#{raw_token.titleize}%"
|
||||
sql << " OR " unless i == 0
|
||||
sql << where_clause
|
||||
tokens.concat([token, token, token])
|
||||
tokens.concat([up_token, up_token]) unless postgres?
|
||||
end
|
||||
[sql, tokens]
|
||||
q_tokens = query.to_s.strip.gsub(/(\s|$|^)/) { "%#{$1}" }
|
||||
[where_clause, [q_tokens, q_tokens]]
|
||||
end
|
||||
|
||||
def self.search(query, user)
|
||||
return [] if query.to_s.blank? || query.to_s.length < 3
|
||||
|
||||
sql, tokens = self.search_query_string(query)
|
||||
|
||||
Person.searchable.where(sql, *tokens).joins(
|
||||
"LEFT OUTER JOIN contacts ON contacts.user_id = #{user.id} AND contacts.person_id = people.id"
|
||||
).includes(:profile
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ class Profile < ActiveRecord::Base
|
|||
end
|
||||
before_save do
|
||||
self.build_tags
|
||||
self.construct_full_name
|
||||
end
|
||||
|
||||
def subscribers(user)
|
||||
|
|
@ -120,6 +121,13 @@ class Profile < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
# Constructs a full name by joining #first_name and #last_name
|
||||
# @returns [String] A full name
|
||||
def construct_full_name
|
||||
self.full_name = [self.first_name, self.last_name].join(' ').downcase
|
||||
self.full_name
|
||||
end
|
||||
|
||||
protected
|
||||
def strip_names
|
||||
self.first_name.strip! if self.first_name
|
||||
|
|
|
|||
22
db/migrate/20110729045734_add_full_name_to_profile.rb
Normal file
22
db/migrate/20110729045734_add_full_name_to_profile.rb
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
class AddFullNameToProfile < ActiveRecord::Migration
|
||||
def self.up
|
||||
add_column :profiles, :full_name, :string, :limit => 70
|
||||
|
||||
add_index :profiles, :full_name
|
||||
add_index :profiles, [:full_name, :searchable]
|
||||
remove_index :profiles, [:first_name, :last_name, :searchable]
|
||||
remove_index :profiles, [:first_name, :searchable]
|
||||
remove_index :profiles, [:last_name, :searchable]
|
||||
|
||||
execute("UPDATE profiles SET full_name=LOWER(CONCAT(first_name, ' ', last_name))")
|
||||
end
|
||||
|
||||
def self.down
|
||||
remove_index :profiles, :column => :full_name
|
||||
remove_column :profiles, :full_name
|
||||
|
||||
add_index :profiles, [:first_name, :searchable]
|
||||
add_index :profiles, [:last_name, :searchable]
|
||||
add_index :profiles, [:first_name, :last_name, :searchable]
|
||||
end
|
||||
end
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# It's strongly recommended to check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 20110710102747) do
|
||||
ActiveRecord::Schema.define(:version => 20110729045734) do
|
||||
|
||||
create_table "aspect_memberships", :force => true do |t|
|
||||
t.integer "aspect_id", :null => false
|
||||
|
|
@ -295,11 +295,11 @@ ActiveRecord::Schema.define(:version => 20110710102747) do
|
|||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "location"
|
||||
t.string "full_name", :limit => 70
|
||||
end
|
||||
|
||||
add_index "profiles", ["first_name", "last_name", "searchable"], :name => "index_profiles_on_first_name_and_last_name_and_searchable"
|
||||
add_index "profiles", ["first_name", "searchable"], :name => "index_profiles_on_first_name_and_searchable"
|
||||
add_index "profiles", ["last_name", "searchable"], :name => "index_profiles_on_last_name_and_searchable"
|
||||
add_index "profiles", ["full_name", "searchable"], :name => "index_profiles_on_full_name_and_searchable"
|
||||
add_index "profiles", ["full_name"], :name => "index_profiles_on_full_name"
|
||||
add_index "profiles", ["person_id"], :name => "index_profiles_on_person_id"
|
||||
|
||||
create_table "service_users", :force => true do |t|
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ describe Person do
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
describe '#diaspora_handle' do
|
||||
context 'local people' do
|
||||
it 'uses the pod config url to set the diaspora_handle' do
|
||||
|
|
|
|||
|
|
@ -29,6 +29,18 @@ describe Profile do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#contruct_full_name' do
|
||||
it 'generates a full name given first and last names' do
|
||||
profile = Factory(:person).profile
|
||||
profile.first_name = "casimiro"
|
||||
profile.last_name = "grippi"
|
||||
|
||||
profile.full_name.should_not == "casimiro grippi"
|
||||
profile.save
|
||||
profile.full_name.should == "casimiro grippi"
|
||||
end
|
||||
end
|
||||
|
||||
describe "of last_name" do
|
||||
it "strips leading and trailing whitespace" do
|
||||
profile = Factory.build(:profile, :last_name => " Ohba ")
|
||||
|
|
|
|||
Loading…
Reference in a new issue