diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d3034464..c7a838612 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## Added - Implement [FEP-67ff](https://codeberg.org/fediverse/fep/src/branch/main/fep/67ff/fep-67ff.md) (federation documentation) +## Fixed +- Meilisearch: order of results returned from our REST API now actually matches how Meilisearch ranks results + ## 2024.04 ## Added diff --git a/lib/pleroma/activity.ex b/lib/pleroma/activity.ex index bf851f808..f820cbdae 100644 --- a/lib/pleroma/activity.ex +++ b/lib/pleroma/activity.ex @@ -258,6 +258,27 @@ def get_create_by_object_ap_id(ap_id) when is_binary(ap_id) do def get_create_by_object_ap_id(_), do: nil + @doc """ + Accepts a list of `ap__id`. + Returns a query yielding Create activities for the given objects, + in the same order as they were specified in the input list. + """ + @spec get_presorted_create_by_object_ap_id([String.t()]) :: Ecto.Queryable.t() + def get_presorted_create_by_object_ap_id(ap_ids) do + from( + a in Activity, + join: + ids in fragment( + "SELECT * FROM UNNEST(?::text[]) WITH ORDINALITY AS ids(ap_id, ord)", + ^ap_ids + ), + on: + ids.ap_id == fragment("?->>'object'", a.data) and + fragment("?->>'type'", a.data) == "Create", + order_by: [asc: ids.ord] + ) + end + @doc """ Accepts `ap_id` or list of `ap_id`. Returns a query. diff --git a/lib/pleroma/search/meilisearch.ex b/lib/pleroma/search/meilisearch.ex index cecb7bd00..822c95b4a 100644 --- a/lib/pleroma/search/meilisearch.ex +++ b/lib/pleroma/search/meilisearch.ex @@ -5,7 +5,6 @@ defmodule Pleroma.Search.Meilisearch do alias Pleroma.Activity import Pleroma.Search.DatabaseSearch - import Ecto.Query @behaviour Pleroma.Search.SearchBackend @@ -91,14 +90,13 @@ def search(user, query, options \\ []) do try do hits - |> Activity.create_by_object_ap_id() + |> Activity.get_presorted_create_by_object_ap_id() |> Activity.with_preloaded_object() |> Activity.restrict_deactivated_users() |> maybe_restrict_local(user) |> maybe_restrict_author(author) |> maybe_restrict_blocked(user) |> maybe_fetch(user, query) - |> order_by([object: obj], desc: obj.data["published"]) |> Pleroma.Repo.all() rescue _ -> maybe_fetch([], user, query) diff --git a/test/pleroma/activity_test.exs b/test/pleroma/activity_test.exs index 4f9144f91..1943746cb 100644 --- a/test/pleroma/activity_test.exs +++ b/test/pleroma/activity_test.exs @@ -41,6 +41,26 @@ test "returns the activity that created an object" do assert activity == found_activity end + test "returns activities by object's AP id in requested presorted order" do + a1 = insert(:note_activity) + o1 = Object.normalize(a1, fetch: false).data["id"] + + a2 = insert(:note_activity) + o2 = Object.normalize(a2, fetch: false).data["id"] + + a3 = insert(:note_activity) + o3 = Object.normalize(a3, fetch: false).data["id"] + + a4 = insert(:note_activity) + o4 = Object.normalize(a4, fetch: false).data["id"] + + found_activities = + Activity.get_presorted_create_by_object_ap_id([o3, o2, o4, o1]) + |> Repo.all() + + assert found_activities == [a3, a2, a4, a1] + end + test "preloading a bookmark" do user = insert(:user) user2 = insert(:user)