I am trying to figure out an elegant way to create an REST API for a site that primarily only deals with slugs
and not ids
. This API is to be written in Node.JS/Express/MongoDB/Mongoose with a Backbone Marionette/Backbone-Relational frontend.
I do not need to ever deal with the typical _id
directly, as I aim for my endpoints to be something like /api/articles/some-article-title
.
I was originally thinking actually using both _ids
and slugs
with something like this, getting it to dynamically return an new id
field.
// Inside my controller
var slugQuery = function(slug){
var query = {$or: [{slug: slug}]};
if (slug.match(/^[0-9a-fA-F]{24}$/)) {
query.$or.push({_id: slug});
}
return query;
}
exports.getProfile = function (req, res) {
var slug = req.params.slug;
Profile.findOne( slugQuery(slug), function(err, profile){
if(err){
// DB Error
res.status(400);
res.end();
}else if(!profile){
res.status(404);
res.end();
}else{
res.json( profile.withId() );
}
});
};
// Method added to the model
ProfileSchema.methods.withId = function() {
var json = this.toObject();
// Use the slug or id
json.id = json.slug || json._id;
return json;
};
This seems hacky to me, especially as there are quite a few endpoints/models that would need to function like this. It gets even more complex when I'm wanting to do fairly deep document linking utilising Mongooses populate
functionality.
I know theoretically you 'can' literally do away with the ObjectID
and store the slug
directly inside the _id field, but you cannot update the _id
field once its been inserted, and also you would need to update all related links to the document if it did indeed change.
To me, this seems like quite a common need, an REST compliant endpoint with slug
based identifiers.
Has anybody had to build something like this before? Any best practices on this?
Thanks!