mojotech / scrivener_ecto

Paginate your Ecto queries with Scrivener
MIT License
573 stars 129 forks source link

Pagination is show older rows again #95

Open sahilpaudel-pe opened 3 years ago

sahilpaudel-pe commented 3 years ago

Below is my implementation I have used order_by condition The data on the first page is fine but when I paginate to other pages I get 1-2 rows every time from previous pages.

{:phoenix_ecto, "~> 4.0.0"},
 {:ecto, "~> 3.4.0"},
 {:ecto_sql, "~> 3.3"},
 {:postgrex, ">= 0.0.0"},
 {:scrivener_ecto, "~> 2.7"},
def all(%{"rule_set_id" => rule_set_id, "is_archived" => is_archived, "page" => page_number}) do
    page = from(rsv in @model,
      where: rsv.rule_set_id == ^rule_set_id and rsv.is_archived == ^is_archived,
      order_by: [desc: rsv.is_live, desc: rsv.start_time]
    )
    # |> Repo.all()
    # |> preload(@default_preloads)
    |> Repo.paginate(page: page_number, page_size: 5)

    {:ok, %{
           "rule_set_versions" => page.entries |> preload(@custom_preloads),
           "page_number" => page.page_number,
           "page_size" => page.page_size,
           "total_pages" => page.total_pages,
           "total_rows" => page.total_entries
          }
    }
  end
la-jose commented 3 years ago

encountering the same issue

jtomaszewski commented 2 years ago

It might that be that when you ask for a page larger than the last one, it'll give you the last one.

So for example if there's 3 pages, and you ask for 100th page, it'll give you results from the 3rd page.

... which I agree, is surprising to me. Maybe it should return no results in such a case?

sahilpaudel-pe commented 2 years ago

yes, it should return no data in such case.

ricardoebbers commented 2 years ago

I had this problem also. The solution is a bit hidden, but possible with the current implementation.

When you use the Scrivener on your Repo, just pass the allow_overflow_page_number: true option, like this:

defmodule MyRepo.Repo do
  use Scrivener, options: [allow_overflow_page_number: true]
  # ...
end

The next time you query a page greater than the total pages, it will return an empty list for entries:

iex(1)> page_params                                               
%{page: 999, page_size: 50}
iex(2)> Actors.get_by_movie(movie, page_params)
%Scrivener.Page{
  entries: [],
  page_number: 999,
  page_size: 50,
  total_entries: 2,
  total_pages: 2
}

You can also pass that config when calling Scrivener.paginate/2 directly.

frm commented 1 year ago

Thanks @ricardoebbers, was having a hard time with this, Scrivener.__using__/1 is lacking in docs for the options. Since you came up with the solution, maybe you could open a PR for others that find the same problem?