X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fuser%2Fsearch.ex;h=6b55df483b76944ba6276f25033ea30f76841628;hb=d3cee000573c5224c5ac1e336809ba09978f7839;hp=fb2f3fedbf627e79cbfe33014062697f8cfb7a19;hpb=c10ce113d487d71c4daa6fabcc641a5caa0d04cb;p=akkoma diff --git a/lib/pleroma/user/search.ex b/lib/pleroma/user/search.ex index fb2f3fedb..6b55df483 100644 --- a/lib/pleroma/user/search.ex +++ b/lib/pleroma/user/search.ex @@ -7,7 +7,6 @@ defmodule Pleroma.User.Search do alias Pleroma.User import Ecto.Query - @similarity_threshold 0.25 @limit 20 def search(query_string, opts \\ []) do @@ -46,41 +45,30 @@ defmodule Pleroma.User.Search do for_user |> base_query(following) |> filter_blocked_user(for_user) + |> filter_invisible_users() |> filter_blocked_domains(for_user) - |> fts_subquery(query_string) - |> subquery() - |> where([u], u.search_rank > @similarity_threshold) + |> fts_search(query_string) + |> trigram_rank(query_string) |> boost_search_rank(for_user) + |> subquery() |> order_by(desc: :search_rank) |> maybe_restrict_local(for_user) end - @nickname_regex ~r/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~\-@]+$/ - defp fts_subquery(query, query_string) do - {nickname_weight, name_weight} = - if String.match?(query_string, @nickname_regex) do - {"A", "B"} - else - {"B", "A"} - end - + defp fts_search(query, query_string) do query_string = to_tsquery(query_string) from( u in query, - select_merge: %{ - search_rank: - fragment( - """ - ts_rank_cd((setweight(to_tsvector('simple', ?), ?) || setweight(to_tsvector('simple', ?), ?)), to_tsquery('simple', ?)) - """, - u.name, - ^name_weight, - u.nickname, - ^nickname_weight, - ^query_string - ) - } + where: + fragment( + """ + (to_tsvector('simple', ?) || to_tsvector('simple', ?)) @@ to_tsquery('simple', ?) + """, + u.name, + u.nickname, + ^query_string + ) ) end @@ -93,17 +81,40 @@ defmodule Pleroma.User.Search do |> Enum.join(" | ") end + defp trigram_rank(query, query_string) do + from( + u in query, + select_merge: %{ + search_rank: + fragment( + "similarity(?, trim(? || ' ' || coalesce(?, '')))", + ^query_string, + u.nickname, + u.name + ) + } + ) + end + defp base_query(_user, false), do: User defp base_query(user, true), do: User.get_followers_query(user) - defp filter_blocked_user(query, %User{info: %{blocks: blocks}}) - when length(blocks) > 0 do - from(q in query, where: not (q.ap_id in ^blocks)) + defp filter_invisible_users(query) do + from(q in query, where: q.invisible == false) + end + + defp filter_blocked_user(query, %User{} = blocker) do + query + |> join(:left, [u], b in Pleroma.UserRelationship, + as: :blocks, + on: b.relationship_type == ^:block and b.source_id == ^blocker.id and u.id == b.target_id + ) + |> where([blocks: b], is_nil(b.target_id)) end defp filter_blocked_user(query, _), do: query - defp filter_blocked_domains(query, %User{info: %{domain_blocks: domain_blocks}}) + defp filter_blocked_domains(query, %User{domain_blocks: domain_blocks}) when length(domain_blocks) > 0 do domains = Enum.join(domain_blocks, ",")