X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fuser%2Fsearch.ex;h=ed06c2ab92f2f367a90c7176279b12bb408b8b42;hb=657277ffc0d3d25be4376ed629057a2d2cefb2e1;hp=f88dffa7be051b1201fb015ded60ce96239d0488;hpb=23db6774cf2a471feb4ae099d49c1f01d98e245c;p=akkoma diff --git a/lib/pleroma/user/search.ex b/lib/pleroma/user/search.ex index f88dffa7b..ed06c2ab9 100644 --- a/lib/pleroma/user/search.ex +++ b/lib/pleroma/user/search.ex @@ -7,45 +7,69 @@ defmodule Pleroma.User.Search do alias Pleroma.User import Ecto.Query - def search(query, opts \\ []) do + @similarity_threshold 0.25 + @limit 20 + + def search(query_string, opts \\ []) do resolve = Keyword.get(opts, :resolve, false) + following = Keyword.get(opts, :following, false) + result_limit = Keyword.get(opts, :limit, @limit) + offset = Keyword.get(opts, :offset, 0) + for_user = Keyword.get(opts, :for_user) # Strip the beginning @ off if there is a query - query = String.trim_leading(query, "@") + query_string = String.trim_leading(query_string, "@") - maybe_resolve(resolve, for_user, query) + maybe_resolve(resolve, for_user, query_string) {:ok, results} = Repo.transaction(fn -> - Ecto.Adapters.SQL.query(Repo, "select set_limit(0.25)", []) + Ecto.Adapters.SQL.query( + Repo, + "select set_limit(#{@similarity_threshold})", + [] + ) - query - |> search_query(for_user) + query_string + |> search_query(for_user, following) + |> paginate(result_limit, offset) |> Repo.all() end) results end - defp search_query(query, for_user) do - query - |> union_query() + defp search_query(query_string, for_user, following) do + for_user + |> base_query(following) + |> search_subqueries(query_string) + |> union_subqueries |> distinct_query() |> boost_search_rank_query(for_user) |> subquery() |> order_by(desc: :search_rank) - |> limit(20) |> maybe_restrict_local(for_user) end - defp union_query(query) do - fts_subquery = fts_search_subquery(query) - trigram_subquery = trigram_search_subquery(query) + defp base_query(_user, false), do: User + defp base_query(user, true), do: User.get_followers_query(user) + + defp paginate(query, limit, offset) do + from(q in query, limit: ^limit, offset: ^offset) + end + defp union_subqueries({fts_subquery, trigram_subquery}) do from(s in trigram_subquery, union_all: ^fts_subquery) end + defp search_subqueries(base_query, query_string) do + { + fts_search_subquery(base_query, query_string), + trigram_search_subquery(base_query, query_string) + } + end + defp distinct_query(q) do from(s in subquery(q), order_by: s.search_type, distinct: s.id) end @@ -102,7 +126,8 @@ defmodule Pleroma.User.Search do ) end - defp fts_search_subquery(term, query \\ User) do + @spec fts_search_subquery(User.t() | Ecto.Query.t(), String.t()) :: Ecto.Query.t() + defp fts_search_subquery(query, term) do processed_query = term |> String.replace(~r/\W+/, " ") @@ -144,9 +169,10 @@ defmodule Pleroma.User.Search do |> User.restrict_deactivated() end - defp trigram_search_subquery(term) do + @spec trigram_search_subquery(User.t() | Ecto.Query.t(), String.t()) :: Ecto.Query.t() + defp trigram_search_subquery(query, term) do from( - u in User, + u in query, select_merge: %{ # ^1 gives 'Postgrex expected a binary, got 1' for some weird reason search_type: fragment("?", 1),