Restify-Mongoose provides a resource abstraction for restify to expose mongoose models as REST resources.
First you'll need to install restify-mongoose via npm
npm install restify-mongoose
Second step is to wire up mongoose and restify using restify-mongoose
var restify = require('restify');
var restifyMongoose = require('restify-mongoose');
var mongoose = require('mongoose');
var server = restify.createServer({
name: 'restify.mongoose.examples.notes',
version: '1.0.0'
});
server.use(restify.acceptParser(server.acceptable));
server.use(restify.queryParser());
server.use(restify.bodyParser());
// Create a simple mongoose model 'Note'
var NoteSchema = new mongoose.Schema({
title : { type : String, required : true },
date : { type : Date, required : true },
tags : [String],
content : { type: String }
});
var Note = mongoose.model('notes', NoteSchema);
// Now create a restify-mongoose resource from 'Note' mongoose model
var notes = restifyMongoose(Note);
// Serve resource notes with fine grained mapping control
server.get('/notes', notes.query());
server.get('/notes/:id', notes.detail());
server.post('/notes', notes.insert());
server.patch('/notes/:id', notes.update());
server.del('/notes/:id', notes.remove());
server.listen(3000, function () {
console.log('%s listening at %s', server.name, server.url);
});
To map resources or resource functionality to restify REST endpoints/routes restify-mongoose offers two approaches:
- 'fine grained mapping' control via list, detail, new, update and delete functions
- 'quick mapping' via serve method
Fine grained mapping
In the above getting started example we used fine grained mapping control. Restify-mongoose defines the functions query
,
detail
, insert
, update
and remove
that return restify route handlers and can be used like this:
// Serve resource notes with fine grained mapping control
server.get('/notes', notes.query());
server.get('/notes/:id', notes.detail());
server.post('/notes', notes.insert());
server.patch('/notes/:id', notes.update());
server.del('/notes/:id', notes.remove());
For every ´id´ dependent function the restify route has to define a :id
placeholder to allow restify-mongoose to access
id parameters. Id dependent functions are detail
, update
and delete
.
Quick mapping
// Serve resource notes with quick mapping
restifyMongoose(models.Note).serve('/api/notes', server);
Maps urls
- GET '/api/notes' to
query
function - GET '/api/notes/:id' to
detail
function - POST '/api/notes' to
insert
function - DELETE '/api/notes/:id' to
remove
function - PATCH '/api/notes/:id' to
update
function
Query parameters are passed by query string parameter q.
Query parameters are parsed as JSON objects and passed to mongoose where query function.
To filter a notes resource by title to match term "first" append the q query parameter to the URL:
http://localhost:3000/notes?q={"title":"first"}
Sort parameters are passed by query string parameter sort.
Sort parameters are passed directly to mongoose sort query function.
To sort a notes resource by title descending append the sort query parameter to the URL:
http://localhost:3000/notes?sort=-title
To restrict selected columns you can pass a query string parameter select.
Select fields are passed directly to mongoose select query function.
To select only date the field of a notes resource append the select query parameter to the URL:
http://localhost:3000/notes?select=date
Results can be filtered with a function, which is set in the options object of the constructor or on the query
and detail
function.
The function takes two parameters: the request object and the response object. The return value of the function is a query that is passed directly to the mongoose where query function.
For instance, you can use a filter to display only results for a particular user:
var filterUser = function(req, res) {
return {user: req.user};
}
var notes = restifyMongoose(Note, {filter: filterUser});
A projection is a function, used by the query
and detail
opersations, which takes the request object, the result model, and a callback. This function should invoke the callback exactly once. This callback takes an error and a model item as it's two parameters. Use null
for the error is there is no error.
For instance, the default detail and list projections are as follows:
function (req, item, cb) {
cb(null, item);
};
A projection is useful if you need to manipulate the result item before returning it in the response. For instance, you may not want to return the passwordHash for a User data model.
// If this is the schema
var UserSchema = new Schema({
username: String,
email: String,
passwordHash: String
});
// This is a projection translating _id to id and not including passwordHash
var userProjection = function(req, item, cb) {
var user = {
id: item._id,
username: item.username,
email: item.email
};
cb(null, user);
};
Projection functions are specified in the options for the resitfy-mongoose contructor, the query function, or the detail function.
For the construtor, the options are listProjection
and detailProjection
var users = restifyMongoose(User, {listProjection: userProjection, detailProjection: userProjection});
users.serve('/users', restifyServer);
For both query and detail, the option is projection
var users = restifyMongoose(User);
users.detail({projection: userProjection});
users.query({projection: userProjection});
- Added
before
andafter
options to theserve
function which pass arrays of handlers to the restify handler chain. - Added
beforeSave
functionality to the insert and update operations. - Added coverage script to package.json
- The insert and update operations now use aync.waterfall
- The server test helper has an optional parameter which will set or not set default routes
- Updates to restify 2.8.x
- Updates to async 0.9.x
- Improved the error message for mongoose validation errors
- Code cleanup
- The
beforeSave
option can now be included in the options passed to therestifyMongoose
constructor.