Order fts results by trigram
authorrinpatch <rinpatch@sdf.org>
Wed, 16 Oct 2019 10:49:33 +0000 (13:49 +0300)
committerrinpatch <rinpatch@sdf.org>
Wed, 16 Oct 2019 10:49:33 +0000 (13:49 +0300)
lib/pleroma/user/search.ex

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