X-Git-Url: https://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fuser%2Fsearch.ex;h=a4f6abca24b358a0764977de3152f5a40a2868a4;hb=9134ef5ecb72f6fe2042f978be3deef41c9b4ce7;hp=7babd47ea542db084a171d373c2b1bc84aaac836;hpb=c5830ac037c0c344bd22b674c41f4dc244a088aa;p=akkoma
diff --git a/lib/pleroma/user/search.ex b/lib/pleroma/user/search.ex
index 7babd47ea..a4f6abca2 100644
--- a/lib/pleroma/user/search.ex
+++ b/lib/pleroma/user/search.ex
@@ -1,10 +1,12 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors
+# Copyright © 2017-2021 Pleroma Authors
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.User.Search do
+ alias Pleroma.EctoType.ActivityPub.ObjectValidators.Uri, as: UriType
alias Pleroma.Pagination
alias Pleroma.User
+
import Ecto.Query
@limit 20
@@ -19,16 +21,47 @@ defmodule Pleroma.User.Search do
query_string = format_query(query_string)
- maybe_resolve(resolve, for_user, query_string)
+ # If this returns anything, it should bounce to the top
+ maybe_resolved = maybe_resolve(resolve, for_user, query_string)
+
+ top_user_ids =
+ []
+ |> maybe_add_resolved(maybe_resolved)
+ |> maybe_add_ap_id_match(query_string)
+ |> maybe_add_uri_match(query_string)
results =
query_string
- |> search_query(for_user, following)
+ |> search_query(for_user, following, top_user_ids)
|> Pagination.fetch_paginated(%{"offset" => offset, "limit" => result_limit}, :offset)
results
end
+ defp maybe_add_resolved(list, {:ok, %User{} = user}) do
+ [user.id | list]
+ end
+
+ defp maybe_add_resolved(list, _), do: list
+
+ defp maybe_add_ap_id_match(list, query) do
+ if user = User.get_cached_by_ap_id(query) do
+ [user.id | list]
+ else
+ list
+ end
+ end
+
+ defp maybe_add_uri_match(list, query) do
+ with {:ok, query} <- UriType.cast(query),
+ q = from(u in User, where: u.uri == ^query, select: u.id),
+ users = Pleroma.Repo.all(q) do
+ users ++ list
+ else
+ _ -> list
+ end
+ end
+
defp format_query(query_string) do
# Strip the beginning @ off if there is a query
query_string = String.trim_leading(query_string, "@")
@@ -47,7 +80,7 @@ defmodule Pleroma.User.Search do
end
end
- defp search_query(query_string, for_user, following) do
+ defp search_query(query_string, for_user, following, top_user_ids) do
for_user
|> base_query(following)
|> filter_blocked_user(for_user)
@@ -55,13 +88,20 @@ defmodule Pleroma.User.Search do
|> filter_internal_users()
|> filter_blocked_domains(for_user)
|> fts_search(query_string)
+ |> select_top_users(top_user_ids)
|> trigram_rank(query_string)
- |> boost_search_rank(for_user)
+ |> boost_search_rank(for_user, top_user_ids)
|> subquery()
|> order_by(desc: :search_rank)
|> maybe_restrict_local(for_user)
end
+ defp select_top_users(query, top_user_ids) do
+ from(u in query,
+ or_where: u.id in ^top_user_ids
+ )
+ end
+
defp fts_search(query, query_string) do
query_string = to_tsquery(query_string)
@@ -175,7 +215,7 @@ defmodule Pleroma.User.Search do
defp local_domain, do: Pleroma.Config.get([Pleroma.Web.Endpoint, :url, :host])
- defp boost_search_rank(query, %User{} = for_user) do
+ defp boost_search_rank(query, %User{} = for_user, top_user_ids) do
friends_ids = User.get_friends_ids(for_user)
followers_ids = User.get_followers_ids(for_user)
@@ -187,6 +227,7 @@ defmodule Pleroma.User.Search do
CASE WHEN (?) THEN (?) * 1.5
WHEN (?) THEN (?) * 1.3
WHEN (?) THEN (?) * 1.1
+ WHEN (?) THEN 9001
ELSE (?) END
""",
u.id in ^friends_ids and u.id in ^followers_ids,
@@ -195,11 +236,26 @@ defmodule Pleroma.User.Search do
u.search_rank,
u.id in ^followers_ids,
u.search_rank,
+ u.id in ^top_user_ids,
u.search_rank
)
}
)
end
- defp boost_search_rank(query, _for_user), do: query
+ defp boost_search_rank(query, _for_user, top_user_ids) do
+ from(u in subquery(query),
+ select_merge: %{
+ search_rank:
+ fragment(
+ """
+ CASE WHEN (?) THEN 9001
+ ELSE (?) END
+ """,
+ u.id in ^top_user_ids,
+ u.search_rank
+ )
+ }
+ )
+ end
end