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
)
)
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,
--- /dev/null
+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
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