Order fts results by trigram

This commit is contained in:
rinpatch 2019-10-16 13:49:33 +03:00
parent c10ce113d4
commit 0a5175ecbb
1 changed files with 30 additions and 18 deletions

View File

@ -7,7 +7,6 @@ defmodule Pleroma.User.Search do
alias Pleroma.User alias Pleroma.User
import Ecto.Query import Ecto.Query
@similarity_threshold 0.25
@limit 20 @limit 20
def search(query_string, opts \\ []) do def search(query_string, opts \\ []) do
@ -47,16 +46,16 @@ defp search_query(query_string, for_user, following) do
|> base_query(following) |> base_query(following)
|> filter_blocked_user(for_user) |> filter_blocked_user(for_user)
|> filter_blocked_domains(for_user) |> filter_blocked_domains(for_user)
|> fts_subquery(query_string) |> fts_search(query_string)
|> subquery() |> trigram_rank(query_string)
|> where([u], u.search_rank > @similarity_threshold)
|> boost_search_rank(for_user) |> boost_search_rank(for_user)
|> subquery()
|> order_by(desc: :search_rank) |> order_by(desc: :search_rank)
|> maybe_restrict_local(for_user) |> maybe_restrict_local(for_user)
end end
@nickname_regex ~r/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~\-@]+$/ @nickname_regex ~r/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~\-@]+$/
defp fts_subquery(query, query_string) do defp fts_search(query, query_string) do
{nickname_weight, name_weight} = {nickname_weight, name_weight} =
if String.match?(query_string, @nickname_regex) do if String.match?(query_string, @nickname_regex) do
{"A", "B"} {"A", "B"}
@ -68,19 +67,17 @@ defp fts_subquery(query, query_string) do
from( from(
u in query, u in query,
select_merge: %{ where:
search_rank: fragment(
fragment( """
""" (setweight(to_tsvector('simple', ?), ?) || setweight(to_tsvector('simple', ?), ?)) @@ to_tsquery('simple', ?)
ts_rank_cd((setweight(to_tsvector('simple', ?), ?) || setweight(to_tsvector('simple', ?), ?)), to_tsquery('simple', ?)) """,
""", u.name,
u.name, ^name_weight,
^name_weight, u.nickname,
u.nickname, ^nickname_weight,
^nickname_weight, ^query_string
^query_string )
)
}
) )
end end
@ -93,6 +90,21 @@ defp to_tsquery(query_string) do
|> Enum.join(" | ") |> Enum.join(" | ")
end 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, false), do: User
defp base_query(user, true), do: User.get_followers_query(user) defp base_query(user, true), do: User.get_followers_query(user)