Search: Add option to search with the websearch function
authorlain <lain@soykaf.club>
Thu, 19 Nov 2020 15:12:01 +0000 (16:12 +0100)
committerlain <lain@soykaf.club>
Thu, 19 Nov 2020 15:12:01 +0000 (16:12 +0100)
lib/pleroma/activity/search.ex
test/pleroma/activity/search_test.exs [new file with mode: 0644]

index ceb365bb3c8b26096a53e42b6637418996a95df8..8449b9b004755b597d7d2ab3aa953d67d37c781f 100644 (file)
@@ -19,11 +19,13 @@ defmodule Pleroma.Activity.Search do
     offset = Keyword.get(options, :offset, 0)
     author = Keyword.get(options, :author)
 
     offset = Keyword.get(options, :offset, 0)
     author = Keyword.get(options, :author)
 
+    search_function = Pleroma.Config.get([:instance, :search_function], :plain)
+
     Activity
     |> Activity.with_preloaded_object()
     |> Activity.restrict_deactivated_users()
     |> restrict_public()
     Activity
     |> Activity.with_preloaded_object()
     |> Activity.restrict_deactivated_users()
     |> restrict_public()
-    |> query_with(index_type, search_query)
+    |> query_with(index_type, search_query, search_function)
     |> maybe_restrict_local(user)
     |> maybe_restrict_author(author)
     |> maybe_restrict_blocked(user)
     |> maybe_restrict_local(user)
     |> maybe_restrict_author(author)
     |> maybe_restrict_blocked(user)
@@ -50,7 +52,7 @@ defmodule Pleroma.Activity.Search do
     )
   end
 
     )
   end
 
-  defp query_with(q, :gin, search_query) do
+  defp query_with(q, :gin, search_query, :plain) do
     from([a, o] in q,
       where:
         fragment(
     from([a, o] in q,
       where:
         fragment(
@@ -61,7 +63,18 @@ defmodule Pleroma.Activity.Search do
     )
   end
 
     )
   end
 
-  defp query_with(q, :rum, search_query) do
+  defp query_with(q, :gin, search_query, :websearch) do
+    from([a, o] in q,
+      where:
+        fragment(
+          "to_tsvector('english', ?->>'content') @@ websearch_to_tsquery('english', ?)",
+          o.data,
+          ^search_query
+        )
+    )
+  end
+
+  defp query_with(q, :rum, search_query, :plain) do
     from([a, o] in q,
       where:
         fragment(
     from([a, o] in q,
       where:
         fragment(
@@ -73,6 +86,18 @@ defmodule Pleroma.Activity.Search do
     )
   end
 
     )
   end
 
+  defp query_with(q, :rum, search_query, :websearch) do
+    from([a, o] in q,
+      where:
+        fragment(
+          "? @@ websearch_to_tsquery('english', ?)",
+          o.fts_content,
+          ^search_query
+        ),
+      order_by: [fragment("? <=> now()::date", o.inserted_at)]
+    )
+  end
+
   defp maybe_restrict_local(q, user) do
     limit = Pleroma.Config.get([:instance, :limit_to_local_content], :unauthenticated)
 
   defp maybe_restrict_local(q, user) do
     limit = Pleroma.Config.get([:instance, :limit_to_local_content], :unauthenticated)
 
diff --git a/test/pleroma/activity/search_test.exs b/test/pleroma/activity/search_test.exs
new file mode 100644 (file)
index 0000000..ba3257d
--- /dev/null
@@ -0,0 +1,45 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Activity.SearchTest do
+  use Pleroma.DataCase
+
+  import Pleroma.Factory
+  alias Pleroma.Web.CommonAPI
+  alias Pleroma.Activity.Search
+
+  test "it finds something" do
+    user = insert(:user)
+    {:ok, post} = CommonAPI.post(user, %{status: "it's wednesday my dudes"})
+
+    [result] = Search.search(nil, "wednesday")
+
+    assert result.id == post.id
+  end
+
+  test "using plainto_tsquery" do
+    clear_config([:instance, :search_function], :plain)
+
+    user = insert(:user)
+    {:ok, post} = CommonAPI.post(user, %{status: "it's wednesday my dudes"})
+    {:ok, _post2} = CommonAPI.post(user, %{status: "it's wednesday my bros"})
+
+    # plainto doesn't understand complex queries
+    assert [result] = Search.search(nil, "wednesday -dudes")
+
+    assert result.id == post.id
+  end
+
+  test "using websearch_to_tsquery" do
+    clear_config([:instance, :search_function], :websearch)
+
+    user = insert(:user)
+    {:ok, _post} = CommonAPI.post(user, %{status: "it's wednesday my dudes"})
+    {:ok, other_post} = CommonAPI.post(user, %{status: "it's wednesday my bros"})
+
+    assert [result] = Search.search(nil, "wednesday -dudes")
+
+    assert result.id == other_post.id
+  end
+end