diff --git a/app/models/user.rb b/app/models/user.rb index d31b946f2..e99a2a9f9 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -6,8 +6,8 @@ class User < ApplicationRecord include Storext.model include PgSearch::Model - pg_search_scope :search_by_username, - against: :username, + pg_search_scope :search_by_name_and_username, + against: %i[name username], using: { tsearch: { prefix: true } } # @citizen428 Preparing to drop profile columns from the users table diff --git a/app/services/search/postgres/username.rb b/app/services/search/postgres/username.rb index 73faba6e1..deaa25550 100644 --- a/app/services/search/postgres/username.rb +++ b/app/services/search/postgres/username.rb @@ -11,7 +11,7 @@ module Search ].freeze def self.search_documents(term) - results = ::User.search_by_username(term).limit(MAX_RESULTS).select(*ATTRIBUTES) + results = ::User.search_by_name_and_username(term).limit(MAX_RESULTS).select(*ATTRIBUTES) serialize(results) end diff --git a/db/migrate/20210420135208_add_name_tsvector_index_to_users.rb b/db/migrate/20210420135208_add_name_tsvector_index_to_users.rb new file mode 100644 index 000000000..530650276 --- /dev/null +++ b/db/migrate/20210420135208_add_name_tsvector_index_to_users.rb @@ -0,0 +1,17 @@ +class AddNameTsvectorIndexToUsers < ActiveRecord::Migration[6.1] + disable_ddl_transaction! + + def up + add_index( + :users, + "to_tsvector('simple'::regconfig, COALESCE((name)::text, ''::text))", + using: :gin, + name: :index_users_on_name_as_tsvector, + algorithm: :concurrently + ) + end + + def down + remove_index :users, name: :index_users_on_name_as_tsvector, algorithm: :concurrently, if_exists: true + end +end diff --git a/db/schema.rb b/db/schema.rb index ea6b364b6..e4b0b4df7 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2021_04_14_033457) do +ActiveRecord::Schema.define(version: 2021_04_20_135208) do # These are extensions that must be enabled in order to support this database enable_extension "citext" @@ -1358,6 +1358,7 @@ ActiveRecord::Schema.define(version: 2021_04_14_033457) do t.boolean "welcome_notifications", default: true, null: false t.datetime "workshop_expiration" t.string "youtube_url" + t.index "to_tsvector('simple'::regconfig, COALESCE((name)::text, ''::text))", name: "index_users_on_name_as_tsvector", using: :gin t.index "to_tsvector('simple'::regconfig, COALESCE((username)::text, ''::text))", name: "index_users_on_username_as_tsvector", using: :gin t.index ["apple_username"], name: "index_users_on_apple_username" t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true diff --git a/spec/requests/search_spec.rb b/spec/requests/search_spec.rb index 96992ae30..2c4d299df 100644 --- a/spec/requests/search_spec.rb +++ b/spec/requests/search_spec.rb @@ -140,7 +140,7 @@ RSpec.describe "Search", type: :request, proper_status: true do allow(Search::User).to receive(:search_usernames).and_return( result, ) - get "/search/usernames" + get search_usernames_path expect(response.parsed_body).to eq("result" => result) end end @@ -155,13 +155,21 @@ RSpec.describe "Search", type: :request, proper_status: true do expect(response.parsed_body["result"]).to be_empty end - it "finds a username by a partial name" do + it "finds a username by a partial username" do user = create(:user, username: "Sloan") get search_usernames_path(username: "slo") expect(response.parsed_body["result"].first).to include("username" => user.username) end + + it "finds a username by a partial name" do + user = create(:user, name: "Sloan") + + get search_usernames_path(username: "slo") + + expect(response.parsed_body["result"].first).to include("username" => user.username) + end end end diff --git a/spec/services/search/postgres/username_spec.rb b/spec/services/search/postgres/username_spec.rb index 73ed9764f..48a0b4088 100644 --- a/spec/services/search/postgres/username_spec.rb +++ b/spec/services/search/postgres/username_spec.rb @@ -29,9 +29,21 @@ RSpec.describe Search::Postgres::Username, type: :service do expect(described_class.search_documents(user.username.first(1))).to be_present end + it "finds a user by their name" do + user = create(:user) + + expect(described_class.search_documents(user.name)).to be_present + end + + it "finds a user by a partial name" do + user = create(:user) + + expect(described_class.search_documents(user.name.first(3))).to be_present + end + it "finds multiple users whose names have common parts", :aggregate_failures do alex = create(:user, username: "alex") - alexsmith = create(:user, username: "alexsmith") + alexsmith = create(:user, name: "alexsmith") rhymes = create(:user, username: "rhymes") result = described_class.search_documents("ale")