README
SluiceBox
Add search, sort and pagination to your plural resource endpoints.
Getting Started
Install Sluice Box:
npm install sluicebox --save
Overview
SluiceBox is a bundle of helpers for creating robust and feature-rich plural resource endpoints. It has helpers for pagination, searching and sorting. It is currently focused on resources stored in MongoDB, but support for other persistent stores may be added in the future. Sluicbox pagination works particularly well with the express-lane enhanced routing library. Sluicebox searching, sorting and pagination works particularly well with the meerkat (and/or timon) wrapper for the mongo-native driver.
Searching
Searches are expressed as a collection of clauses joined by conjunctions: ;
(and) to further refine a search, |
(or) to broaden the search. Clauses may be either simple predicates or groups of subordinate clauses joined together by conjunctions and wrapped in parenthesis (...)
. Predicates are composed of a field name and a value separated by a comparison. Comparisons are either a lone comparator or a !
(not) followed by a comparator. The currently supported comparators are: :
(equal), *
(contains), ^
(starts with), $
(ends_with), <
(less than) and >
(greater than).
A simple search to find all users that have a gmail email address could be expressed as:
/api/versions/1/users?q=email$gmail.com
To refine our search to only active users we can simply add another predicate:
/api/versions/1/users?q=email$gmail.com;state:active
A complex search to find all active users with either gmail or yahoo addresses could be expressed as:
/api/versions/1/users?q=state:active;(email$gmail.com|email$yahoo.com)
The Code
This example contains constructs from express-lane and timon for simplicity.
sluicebox = require('sluicebox')()
{ Account } = require '../models'
module.exports =
get: (req, res, next) ->
sluicebox.search req.query.q,
(query) ->
Account(req).find(query).all (accounts) ->
res.json { accounts }
(error) ->
res.status(422).json error
Sorting
Sorting is specified as a comma separated list of one or more sort descriptors. A sort descriptor is a field name optionally followed by a direction. A direction is one of asc
or desc
. When a direction is not specified the descriptor defaults to asc
.
A simple sort that orders the results lexicographically by last name could be expressed as:
/api/versions/1/users?sort=name.last asc
or
/api/versions/1/users?sort=name.last
A simple sort that orders the most recently created accounts first could be expressed as:
/api/verisons/1/users?sort=created_at desc
A compound sort that orders the results lexicographically by last name and orders people who have the last name lexicographically by first name could be expressed as:
/api/versions/1/users?sort=name.last,name.first
The Code
Lets add sorting to our previous example.
sluicebox = require('sluicebox')()
{ Account } = require '../models'
module.exports =
get: (req, res, next) ->
sluicebox.search req.query.q,
(query) ->
sort = sluicebox.sort req.query.sort
Account(req).find(query).sort(sort).all (accounts) ->
res.json { accounts }
(error) ->
res.status(422).json error
Pagination
The pagination complete with hypermedia can be easily added to result sets. This is particularly easy when paired with meerkat or timon.
The third page of a result set with 20 results per page could be requested as:
/api/versions/1/users?page=3&per=20
The Code
Lets add pagination to our previous example.
sluicebox = require('sluicebox')()
{ Account } = require '../models'
module.exports =
get: (req, res, next) ->
sluicebox.search req.query.q,
(query) ->
sort = sluicebox.sort req.query.sort
page = req.query.page ? 1
per = req.query.per ? 100
Account(req).find(query).sort(sort).paginate page, per, (accounts, pagination) ->
pagination = sluicebox.paginate 'accounts', req, res, pagination
res.json { accounts, pagination }
(error) ->
res.status(422).json error
Contributing
In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality.
Release History
(Nothing yet)