diff --git a/lib/mobilizon/events/events.ex b/lib/mobilizon/events/events.ex index 4d68b9d41..7bf770723 100644 --- a/lib/mobilizon/events/events.ex +++ b/lib/mobilizon/events/events.ex @@ -602,7 +602,7 @@ defmodule Mobilizon.Events do |> filter_local_or_from_followed_instances_events() |> filter_public_visibility() |> event_order(Map.get(args, :sort_by, :match_desc), search_string) - |> Page.build_page(page, limit, :begins_on) + |> Page.build_page(page, limit) end @doc """ diff --git a/lib/mobilizon/instances/instances.ex b/lib/mobilizon/instances/instances.ex index db0dafd29..8d6557877 100644 --- a/lib/mobilizon/instances/instances.ex +++ b/lib/mobilizon/instances/instances.ex @@ -73,7 +73,7 @@ defmodule Mobilizon.Instances do query end - %Page{elements: elements} = paged_instances = Page.build_page(query, page, limit, :domain) + %Page{elements: elements} = paged_instances = Page.build_page(query, page, limit) %Page{ paged_instances diff --git a/lib/mobilizon/storage/page.ex b/lib/mobilizon/storage/page.ex index 9b094d4e8..9a8537774 100644 --- a/lib/mobilizon/storage/page.ex +++ b/lib/mobilizon/storage/page.ex @@ -23,11 +23,22 @@ defmodule Mobilizon.Storage.Page do `field` is use to define the field that will be used for the count aggregate, which should be the same as the field used for order_by See https://stackoverflow.com/q/12693089/10204399 """ - @spec build_page(Ecto.Queryable.t(), integer | nil, integer | nil, atom()) :: t(any) - def build_page(query, page, limit, field \\ :id) do + @spec build_page(Ecto.Queryable.t(), integer | nil, integer) :: t(any) + def build_page(query, page, limit) do + count_query = + query + # Exclude select because we add a new one below + |> exclude(:select) + # Exclude order_by for perf + |> exclude(:order_by) + # Exclude preloads to avoid error "cannot preload associations in subquery" + |> exclude(:preload) + |> subquery() + |> select([r], count(fragment("*"))) + [total, elements] = [ - fn -> Repo.aggregate(query, :count, field) end, + fn -> Repo.one(count_query) end, fn -> Repo.all(paginate(query, page, limit)) end ] |> Enum.map(&Task.async/1)