forked from AkkomaGang/akkoma
Ensure fts is prefered over trigram and use union_all instead of union in user search query
This commit is contained in:
parent
519a294d0f
commit
3229c7a1d6
2 changed files with 18 additions and 5 deletions
|
@ -50,6 +50,7 @@ defmodule Pleroma.User do
|
||||||
field(:local, :boolean, default: true)
|
field(:local, :boolean, default: true)
|
||||||
field(:follower_address, :string)
|
field(:follower_address, :string)
|
||||||
field(:search_rank, :float, virtual: true)
|
field(:search_rank, :float, virtual: true)
|
||||||
|
field(:search_type, :integer, virtual: true)
|
||||||
field(:tags, {:array, :string}, default: [])
|
field(:tags, {:array, :string}, default: [])
|
||||||
field(:bookmarks, {:array, :string}, default: [])
|
field(:bookmarks, {:array, :string}, default: [])
|
||||||
field(:last_refreshed_at, :naive_datetime_usec)
|
field(:last_refreshed_at, :naive_datetime_usec)
|
||||||
|
@ -835,8 +836,8 @@ def search(query, resolve \\ false, for_user \\ nil) do
|
||||||
def search_query(query, for_user) do
|
def search_query(query, for_user) do
|
||||||
fts_subquery = fts_search_subquery(query)
|
fts_subquery = fts_search_subquery(query)
|
||||||
trigram_subquery = trigram_search_subquery(query)
|
trigram_subquery = trigram_search_subquery(query)
|
||||||
union_query = from(s in trigram_subquery, union: ^fts_subquery)
|
union_query = from(s in trigram_subquery, union_all: ^fts_subquery)
|
||||||
distinct_query = from(s in subquery(union_query), distinct: s.id)
|
distinct_query = from(s in subquery(union_query), order_by: s.search_type, distinct: s.id)
|
||||||
|
|
||||||
from(s in subquery(boost_search_rank_query(distinct_query, for_user)),
|
from(s in subquery(boost_search_rank_query(distinct_query, for_user)),
|
||||||
order_by: [desc: s.search_rank],
|
order_by: [desc: s.search_rank],
|
||||||
|
@ -884,6 +885,7 @@ defp fts_search_subquery(term, query \\ User) do
|
||||||
from(
|
from(
|
||||||
u in query,
|
u in query,
|
||||||
select_merge: %{
|
select_merge: %{
|
||||||
|
search_type: ^0,
|
||||||
search_rank:
|
search_rank:
|
||||||
fragment(
|
fragment(
|
||||||
"""
|
"""
|
||||||
|
@ -916,6 +918,8 @@ defp trigram_search_subquery(term) do
|
||||||
from(
|
from(
|
||||||
u in User,
|
u in User,
|
||||||
select_merge: %{
|
select_merge: %{
|
||||||
|
# ^1 gives 'Postgrex expected a binary, got 1' for some weird reason
|
||||||
|
search_type: fragment("?", 1),
|
||||||
search_rank:
|
search_rank:
|
||||||
fragment(
|
fragment(
|
||||||
"similarity(?, trim(? || ' ' || coalesce(?, '')))",
|
"similarity(?, trim(? || ' ' || coalesce(?, '')))",
|
||||||
|
|
|
@ -879,7 +879,11 @@ test "finds a user by full or partial nickname" do
|
||||||
user = insert(:user, %{nickname: "john"})
|
user = insert(:user, %{nickname: "john"})
|
||||||
|
|
||||||
Enum.each(["john", "jo", "j"], fn query ->
|
Enum.each(["john", "jo", "j"], fn query ->
|
||||||
assert user == User.search(query) |> List.first() |> Map.put(:search_rank, nil)
|
assert user ==
|
||||||
|
User.search(query)
|
||||||
|
|> List.first()
|
||||||
|
|> Map.put(:search_rank, nil)
|
||||||
|
|> Map.put(:search_type, nil)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -887,7 +891,11 @@ test "finds a user by full or partial name" do
|
||||||
user = insert(:user, %{name: "John Doe"})
|
user = insert(:user, %{name: "John Doe"})
|
||||||
|
|
||||||
Enum.each(["John Doe", "JOHN", "doe", "j d", "j", "d"], fn query ->
|
Enum.each(["John Doe", "JOHN", "doe", "j d", "j", "d"], fn query ->
|
||||||
assert user == User.search(query) |> List.first() |> Map.put(:search_rank, nil)
|
assert user ==
|
||||||
|
User.search(query)
|
||||||
|
|> List.first()
|
||||||
|
|> Map.put(:search_rank, nil)
|
||||||
|
|> Map.put(:search_type, nil)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -941,6 +949,7 @@ test "finds a user whose name is nil" do
|
||||||
User.search("lain@pleroma.soykaf.com")
|
User.search("lain@pleroma.soykaf.com")
|
||||||
|> List.first()
|
|> List.first()
|
||||||
|> Map.put(:search_rank, nil)
|
|> Map.put(:search_rank, nil)
|
||||||
|
|> Map.put(:search_type, nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "does not yield false-positive matches" do
|
test "does not yield false-positive matches" do
|
||||||
|
@ -958,7 +967,7 @@ test "works with URIs" do
|
||||||
user = User.get_by_ap_id("http://mastodon.example.org/users/admin")
|
user = User.get_by_ap_id("http://mastodon.example.org/users/admin")
|
||||||
|
|
||||||
assert length(results) == 1
|
assert length(results) == 1
|
||||||
assert user == result |> Map.put(:search_rank, nil)
|
assert user == result |> Map.put(:search_rank, nil) |> Map.put(:search_type, nil)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue