From 123352ffa1c80aab658fca0c2276d1c06de43a02 Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Wed, 8 Jul 2020 22:50:15 +0300 Subject: [PATCH] Removed unused trigram index on `users`. Fixed `users_fts_index` usage. --- lib/pleroma/user/search.ex | 16 +++++++++++----- .../20200708193702_drop_user_trigram_index.exs | 18 ++++++++++++++++++ test/user_search_test.exs | 12 ++++-------- 3 files changed, 33 insertions(+), 13 deletions(-) create mode 100644 priv/repo/migrations/20200708193702_drop_user_trigram_index.exs diff --git a/lib/pleroma/user/search.ex b/lib/pleroma/user/search.ex index 7ff1c7e24..d4fd31069 100644 --- a/lib/pleroma/user/search.ex +++ b/lib/pleroma/user/search.ex @@ -69,11 +69,15 @@ defp fts_search(query, query_string) do u in query, where: fragment( + # The fragment must _exactly_ match `users_fts_index`, otherwise the index won't work """ - (to_tsvector('simple', ?) || to_tsvector('simple', ?)) @@ to_tsquery('simple', ?) + ( + setweight(to_tsvector('simple', regexp_replace(?, '\\W', ' ', 'g')), 'A') || + setweight(to_tsvector('simple', regexp_replace(coalesce(?, ''), '\\W', ' ', 'g')), 'B') + ) @@ to_tsquery('simple', ?) """, - u.name, u.nickname, + u.name, ^query_string ) ) @@ -95,9 +99,11 @@ defp trigram_rank(query, query_string) do select_merge: %{ search_rank: fragment( - "similarity(?, ?) + \ - similarity(?, regexp_replace(?, '@.+', '')) + \ - similarity(?, trim(coalesce(?, '')))", + """ + similarity(?, ?) + + similarity(?, regexp_replace(?, '@.+', '')) + + similarity(?, trim(coalesce(?, ''))) + """, ^query_string, u.nickname, ^query_string, diff --git a/priv/repo/migrations/20200708193702_drop_user_trigram_index.exs b/priv/repo/migrations/20200708193702_drop_user_trigram_index.exs new file mode 100644 index 000000000..94efe323a --- /dev/null +++ b/priv/repo/migrations/20200708193702_drop_user_trigram_index.exs @@ -0,0 +1,18 @@ +defmodule Pleroma.Repo.Migrations.DropUserTrigramIndex do + @moduledoc "Drops unused trigram index on `users` (FTS index is being used instead)" + + use Ecto.Migration + + def up do + drop_if_exists(index(:users, [], name: :users_trigram_index)) + end + + def down do + create_if_not_exists( + index(:users, ["(trim(nickname || ' ' || coalesce(name, ''))) gist_trgm_ops"], + name: :users_trigram_index, + using: :gist + ) + ) + end +end diff --git a/test/user_search_test.exs b/test/user_search_test.exs index 758822072..559ba5966 100644 --- a/test/user_search_test.exs +++ b/test/user_search_test.exs @@ -72,15 +72,11 @@ test "finds a user by full name or leading fragment(s) of its words" do end) end - test "is not [yet] capable of matching by non-leading fragments (e.g. by domain)" do - user1 = insert(:user, %{nickname: "iamthedude"}) - insert(:user, %{nickname: "arandom@dude.com"}) + test "matches by leading fragment of user domain" do + user = insert(:user, %{nickname: "arandom@dude.com"}) + insert(:user, %{nickname: "iamthedude"}) - assert [] == User.search("dude") - - # Matching by leading fragment works, though - user1_id = user1.id - assert ^user1_id = User.search("iam") |> List.first() |> Map.get(:id) + assert [user.id] == User.search("dud") |> Enum.map(& &1.id) end test "ranks full nickname match higher than full name match" do