# Paginator
[](https://travis-ci.org/duffelhq/paginator)
[](http://inch-ci.org/github/duffelhq/paginator)
[Cursor based pagination](http://use-the-index-luke.com/no-offset) for Elixir [Ecto](https://github.com/elixir-ecto/ecto).
[Documentation](https://hexdocs.pm/paginator)
## Getting started
```elixir
defmodule MyApp.Repo do
use Ecto.Repo, otp_app: :my_app
use Paginator
end
query = from(p in Post, order_by: [asc: p.inserted_at, asc: p.id])
page = MyApp.Repo.paginate(query, cursor_fields: [:inserted_at, :id], limit: 50)
# `page.entries` contains all the entries for this page.
# `page.metadata` contains the metadata associated with this page (cursors, limit, total count)
```
## Install
Add `paginator` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[{:paginator, "~> 0.1"}]
end
```
## Usage
1. Add `Paginator` to your repo.
```elixir
defmodule MyApp.Repo do
use Ecto.Repo, otp_app: :my_app
use Paginator
end
```
2. Use the `paginate` function to paginate your queries.
```elixir
query = from(p in Post, order_by: [asc: p.inserted_at, asc: p.id])
# return the first 50 posts
%{entries: entries, metadata: metadata} = Repo.paginate(query, cursor_fields: [:inserted_at, :id], limit: 50)
# assign the `after` cursor to a variable
cursor_after = metadata.after
# return the next 50 posts
%{entries: entries, metadata: metadata} = Repo.paginate(query, after: cursor_after, cursor_fields: [:inserted_at, :id], limit: 50)
# assign the `after` cursor to a variable
cursor_before = metadata.before
# return the previous 50 posts (if no post was created in between it should be the same list as in our first call to `paginate`)
%{entries: entries, metadata: metadata} = Repo.paginate(query, before: cursor_before, cursor_fields: [:inserted_at, :id], limit: 50)
# return total count
# NOTE: this will issue a separate `SELECT COUNT(*) FROM table` query to the database.
%{entries: entries, metadata: metadata} = Repo.paginate(query, include_total_count: true, cursor_fields: [:inserted_at, :id], limit: 50)
IO.puts "total count: #{metadata.total_count}"
```
## Caveats
* This library has only be tested with PostgreSQL.
* You need to add order_by clauses yourself before passing your query to `paginate/2`. In the future we might do that
for you automatically based on the fields specified in `:cursor_fields`.
* It is not possible to use the column from a joined resource as a cursor. This limitation will be lifted once support for
[named joints](https://github.com/elixir-ecto/ecto/issues/2389) lands in Ecto 3.0.
* There is an outstanding issue where Postgrex fails to properly builds the query if it includes custom PostgreSQL types.
## Documentation
Documentation is written into the library, you will find it in the source code, accessible from `iex` and of course, it
all gets published to [hexdocs](http://hexdocs.pm/paginator).
## Contributing
### Running tests
Clone the repo and fetch its dependencies:
```
$ git clone https://github.com/duffelhq/paginator.git
$ cd paginator
$ mix deps.get
$ mix test
```
### Building docs
```
$ mix docs
```
## LICENSE
See [LICENSE](https://github.com/duffelhq/paginator/blob/master/LICENSE.txt)