forked from AkkomaGang/akkoma
Merge branch '2182-profile-search-improvements' into 'develop'
Resolve "Profile search by URL doesn't work correctly" Closes #2182 See merge request pleroma/pleroma!3030
This commit is contained in:
commit
c788593f7f
3 changed files with 59 additions and 6 deletions
|
@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
- Search: Users are now findable by their urls.
|
||||||
- Renamed `:await_up_timeout` in `:connections_pool` namespace to `:connect_timeout`, old name is deprecated.
|
- Renamed `:await_up_timeout` in `:connections_pool` namespace to `:connect_timeout`, old name is deprecated.
|
||||||
- Renamed `:timeout` in `pools` namespace to `:recv_timeout`, old name is deprecated.
|
- Renamed `:timeout` in `pools` namespace to `:recv_timeout`, old name is deprecated.
|
||||||
- The `discoverable` field in the `User` struct will now add a NOINDEX metatag to profile pages when false.
|
- The `discoverable` field in the `User` struct will now add a NOINDEX metatag to profile pages when false.
|
||||||
|
|
|
@ -19,11 +19,21 @@ def search(query_string, opts \\ []) do
|
||||||
|
|
||||||
query_string = format_query(query_string)
|
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)
|
||||||
|
maybe_ap_id_match = User.get_cached_by_ap_id(query_string)
|
||||||
|
|
||||||
|
top_user_ids =
|
||||||
|
case {maybe_resolved, maybe_ap_id_match} do
|
||||||
|
{{:ok, %User{} = user}, %User{} = other_user} -> [user.id, other_user.id]
|
||||||
|
{{:ok, %User{} = user}, _} -> [user.id]
|
||||||
|
{_, %User{} = user} -> [user.id]
|
||||||
|
_ -> []
|
||||||
|
end
|
||||||
|
|
||||||
results =
|
results =
|
||||||
query_string
|
query_string
|
||||||
|> search_query(for_user, following)
|
|> search_query(for_user, following, top_user_ids)
|
||||||
|> Pagination.fetch_paginated(%{"offset" => offset, "limit" => result_limit}, :offset)
|
|> Pagination.fetch_paginated(%{"offset" => offset, "limit" => result_limit}, :offset)
|
||||||
|
|
||||||
results
|
results
|
||||||
|
@ -47,7 +57,7 @@ defp format_query(query_string) do
|
||||||
end
|
end
|
||||||
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
|
for_user
|
||||||
|> base_query(following)
|
|> base_query(following)
|
||||||
|> filter_blocked_user(for_user)
|
|> filter_blocked_user(for_user)
|
||||||
|
@ -56,13 +66,20 @@ defp search_query(query_string, for_user, following) do
|
||||||
|> filter_internal_users()
|
|> filter_internal_users()
|
||||||
|> filter_blocked_domains(for_user)
|
|> filter_blocked_domains(for_user)
|
||||||
|> fts_search(query_string)
|
|> fts_search(query_string)
|
||||||
|
|> select_top_users(top_user_ids)
|
||||||
|> trigram_rank(query_string)
|
|> trigram_rank(query_string)
|
||||||
|> boost_search_rank(for_user)
|
|> boost_search_rank(for_user, top_user_ids)
|
||||||
|> subquery()
|
|> subquery()
|
||||||
|> order_by(desc: :search_rank)
|
|> order_by(desc: :search_rank)
|
||||||
|> maybe_restrict_local(for_user)
|
|> maybe_restrict_local(for_user)
|
||||||
end
|
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
|
defp fts_search(query, query_string) do
|
||||||
query_string = to_tsquery(query_string)
|
query_string = to_tsquery(query_string)
|
||||||
|
|
||||||
|
@ -180,7 +197,7 @@ defp restrict_local(q), do: where(q, [u], u.local == true)
|
||||||
|
|
||||||
defp local_domain, do: Pleroma.Config.get([Pleroma.Web.Endpoint, :url, :host])
|
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)
|
friends_ids = User.get_friends_ids(for_user)
|
||||||
followers_ids = User.get_followers_ids(for_user)
|
followers_ids = User.get_followers_ids(for_user)
|
||||||
|
|
||||||
|
@ -192,6 +209,7 @@ defp boost_search_rank(query, %User{} = for_user) do
|
||||||
CASE WHEN (?) THEN (?) * 1.5
|
CASE WHEN (?) THEN (?) * 1.5
|
||||||
WHEN (?) THEN (?) * 1.3
|
WHEN (?) THEN (?) * 1.3
|
||||||
WHEN (?) THEN (?) * 1.1
|
WHEN (?) THEN (?) * 1.1
|
||||||
|
WHEN (?) THEN 9001
|
||||||
ELSE (?) END
|
ELSE (?) END
|
||||||
""",
|
""",
|
||||||
u.id in ^friends_ids and u.id in ^followers_ids,
|
u.id in ^friends_ids and u.id in ^followers_ids,
|
||||||
|
@ -200,11 +218,26 @@ defp boost_search_rank(query, %User{} = for_user) do
|
||||||
u.search_rank,
|
u.search_rank,
|
||||||
u.id in ^followers_ids,
|
u.id in ^followers_ids,
|
||||||
u.search_rank,
|
u.search_rank,
|
||||||
|
u.id in ^top_user_ids,
|
||||||
u.search_rank
|
u.search_rank
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
end
|
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
|
end
|
||||||
|
|
|
@ -17,6 +17,25 @@ defmodule Pleroma.UserSearchTest do
|
||||||
describe "User.search" do
|
describe "User.search" do
|
||||||
setup do: clear_config([:instance, :limit_to_local_content])
|
setup do: clear_config([:instance, :limit_to_local_content])
|
||||||
|
|
||||||
|
test "returns a resolved user as the first result" do
|
||||||
|
Pleroma.Config.put([:instance, :limit_to_local_content], false)
|
||||||
|
user = insert(:user, %{nickname: "no_relation", ap_id: "https://lain.com/users/lain"})
|
||||||
|
_user = insert(:user, %{nickname: "com_user"})
|
||||||
|
|
||||||
|
[first_user, _second_user] = User.search("https://lain.com/users/lain", resolve: true)
|
||||||
|
|
||||||
|
assert first_user.id == user.id
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns a user with matching ap_id as the first result" do
|
||||||
|
user = insert(:user, %{nickname: "no_relation", ap_id: "https://lain.com/users/lain"})
|
||||||
|
_user = insert(:user, %{nickname: "com_user"})
|
||||||
|
|
||||||
|
[first_user, _second_user] = User.search("https://lain.com/users/lain")
|
||||||
|
|
||||||
|
assert first_user.id == user.id
|
||||||
|
end
|
||||||
|
|
||||||
test "excludes invisible users from results" do
|
test "excludes invisible users from results" do
|
||||||
user = insert(:user, %{nickname: "john t1000"})
|
user = insert(:user, %{nickname: "john t1000"})
|
||||||
insert(:user, %{invisible: true, nickname: "john t800"})
|
insert(:user, %{invisible: true, nickname: "john t800"})
|
||||||
|
|
Loading…
Reference in a new issue