Safe Haskell | None |
---|---|
Language | Haskell2010 |
This module provides efficient pagination over your database queries.
No OFFSET
here - we use ranges to do this right!
The ideal "range" column for a datatype has a few properties:
- It should have an index. An index on the column will dramatically improve performance on pagination.
- It should be monotonic - that is, we shouldn't be able to insert new
data into the middle of a range. An example would be a
created_at
timestamp field, or a auto-incrementing primary key.
This module offers two ways to page through a database. You can use the
streamingEntities
to get a ConduitT
of
values
streaming out. Or, if you'd like finer control, you can use Entity
recordgetPage
to get the first page of data, and then nextPage
to get the next
possible page of data.
Synopsis
- data Page record typ = Page {
- pageRecords :: [Entity record]
- pageRecordCount :: Int
- pageRange :: Range typ
- pageDesiredRange :: DesiredRange typ
- pageField :: EntityField record typ
- pageFilters :: [Filter record]
- pageSize :: PageSize
- pageSortOrder :: SortOrder
- streamEntities :: forall record backend typ m a. (PersistRecordBackend record backend, PersistQueryRead backend, Ord typ, PersistField typ, MonadIO m) => [Filter record] -> EntityField record typ -> PageSize -> SortOrder -> DesiredRange typ -> ConduitT a (Entity record) (ReaderT backend m) ()
- rangeToFilters :: PersistField typ => Range (Maybe typ) -> EntityField record typ -> [Filter record]
- getPage :: forall record backend typ m. (PersistRecordBackend record backend, PersistQueryRead backend, Ord typ, PersistField typ, MonadIO m) => [Filter record] -> EntityField record typ -> PageSize -> SortOrder -> DesiredRange typ -> ReaderT backend m (Maybe (Page record typ))
- nextPage :: (PersistRecordBackend record backend, PersistQueryRead backend, Ord typ, PersistField typ, MonadIO m) => Page record typ -> ReaderT backend m (Maybe (Page record typ))
- module Database.Persist.Pagination.Types
Documentation
A
describes a list of records and enough
information necessary to acquire the next page of records, if possible.Page
record typ
Since: 0.1.0.0
Page | |
|
:: forall record backend typ m a. (PersistRecordBackend record backend, PersistQueryRead backend, Ord typ, PersistField typ, MonadIO m) | |
=> [Filter record] | The filters to apply. |
-> EntityField record typ | The field to sort on. This field should have an index on it, and
ideally, the field should be monotonic - that is, you can only
insert values at either extreme end of the range. A |
-> PageSize | How many records in a page |
-> SortOrder | Ascending or descending |
-> DesiredRange typ | The desired range. Provide |
-> ConduitT a (Entity record) (ReaderT backend m) () |
Stream entities out of the database, only pulling a limited amount into memory at a time.
You should use this instead of selectSource
because selectSource
doesn't really work. It doesn't work at all in MySQL, and it's somewhat
sketchy with PostgreSQL and SQLite. This function is guaranteed to use
only as much memory as a single page, and if you tune the page size
right, you'll get efficient queries from the database.
There's an open issue for selectSource
not working:
GitHub Issue.
Since: 0.1.0.0
rangeToFilters :: PersistField typ => Range (Maybe typ) -> EntityField record typ -> [Filter record] Source #
Convert a
into a list of DesiredRange
typFilter
s for the query.
The DesiredRange
is treated as an exclusive range.
Since: 0.1.0.0
:: forall record backend typ m. (PersistRecordBackend record backend, PersistQueryRead backend, Ord typ, PersistField typ, MonadIO m) | |
=> [Filter record] | The filters to apply. |
-> EntityField record typ | The field to sort on. This field should have an index on it, and
ideally, the field should be monotonic - that is, you can only
insert values at either extreme end of the range. A |
-> PageSize | How many records in a page |
-> SortOrder | Ascending or descending |
-> DesiredRange typ | The desired range. Provide |
-> ReaderT backend m (Maybe (Page record typ)) |
Get the first Page
according to the given criteria. This returns
a
, because there may not actually be any records that
correspond to the query you issue. You can call Maybe
Page
pageRecords
on the
result object to get the row of records for this page, and you can call
nextPage
with the Page
object to get the next page, if one exists.
This function gives you lower level control over pagination than the
streamEntities
function.
Since: 0.1.0.0
nextPage :: (PersistRecordBackend record backend, PersistQueryRead backend, Ord typ, PersistField typ, MonadIO m) => Page record typ -> ReaderT backend m (Maybe (Page record typ)) Source #
Retrieve the next Page
of data, if possible.
Since: 0.1.0.0