PERF: exact email match bypass

instead of scanning full table when there is an exact email match ONLY
return the actual user.
This commit is contained in:
Sam 2017-11-09 16:53:14 +11:00
parent 86e6732f78
commit 2d5bf0705a
2 changed files with 29 additions and 4 deletions

View File

@ -101,13 +101,26 @@ class AdminUserIndexQuery
end
end
def filter_by_user_with_bypass(filter)
if filter =~ /.+@.+/
# probably an email so try the bypass
user_id = UserEmail.where(email: filter.downcase).pluck(:user_id).first
if user_id
return @query.where('users.id = ?', user_id)
end
end
@query.where('username_lower ILIKE :filter OR user_emails.email ILIKE :filter', filter: "%#{params[:filter]}%")
end
def filter_by_search
if params[:filter].present?
params[:filter].strip!
if ip = IPAddr.new(params[:filter]) rescue nil
filter = params[:filter]
if filter.present?
filter.strip!
if ip = IPAddr.new(filter) rescue nil
@query.where('ip_address <<= :ip OR registration_ip_address <<= :ip', ip: ip.to_cidr_s)
else
@query.where('username_lower ILIKE :filter OR user_emails.email ILIKE :filter', filter: "%#{params[:filter]}%")
filter_by_user_with_bypass(filter)
end
end
end

View File

@ -178,6 +178,18 @@ describe AdminUserIndexQuery do
describe "filtering" do
context "exact email bypass" do
it "can correctly bypass expensive ilike query" do
user = Fabricate(:user, email: 'sam@Sam.com')
query = AdminUserIndexQuery.new(filter: 'Sam@sam.com').find_users_query
expect(query.count).to eq(1)
expect(query.first.id).to eq(user.id)
expect(query.to_sql.downcase).not_to include("ilike")
end
end
context "by email fragment" do
before(:each) { Fabricate(:user, email: "test1@example.com") }