Reputation:
I have a slug
attribute that I'm setting to unique with Mongoose:
// Article
var Article = new Schema({
title: { type: String, required: true },
heading: { type: String },
body: { type: String, required: true },
is_premium: { type: Boolean, required: true },
urlslug: { type: String, unique: true, required: true },
images: [Images],
videos: [Videos],
user: {
user_id: { type: String, required: true },
url: { type: String, required: true }
},
modified: { type: Date, required: true }
});
Article.path('title').validate(function (v) {
return v.length > 5 && v.length < 70;
});
I'm posting it successfully to the database like this:
router.post('/', passport.authenticate('bearer', { session: false }), function (req, res) {
if (req.user.role === "editor" || req.user.role === "moderator" || req.user.role === "admin") {
var article = new ArticleModel({
title: req.body.title,
heading: req.body.heading,
body: req.body.body,
images: req.body.images,
videos: req.body.videos,
is_premium: req.body.is_premium,
urlslug: req.body.slug,
modified: Date.now(),
user: {
user_id: req.user.id,
url: userUrlPrefix + req.user.username
}
});
article.save(function (err) {
if (!err) {
log.info("article created");
return res.send({ status: 'OK', article:article });
} else {
console.log(err);
if(err.name == 'ValidationError') {
res.statusCode = 400;
res.send({ error: 'Validation error' });
} else {
res.statusCode = 500;
res.send({ error: 'Server error' });
}
log.error('Internal error(%d): %s',res.statusCode,err.message);
}
});
} else {
return res.send('your user can\'t create content');
}
});
When I try to use the same slug again, and ideally trigger a validation error, I get a server error, not a validation error:
HTTP/1.1 500 Internal Server Error
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 24
Content-Type: application/json; charset=utf-8
Date: Fri, 30 Jan 2015 23:07:56 GMT
Vary: Origin
X-Powered-By: Express
{
"error": "Server error"
}
(output from my node console):
{ [MongoError: insertDocument :: caused by :: 11000 E11000 duplicate key error
index: SSR.articles.$urlslug_1 dup key: { : "article-1" }]
name: 'MongoError',
code: 11000,
err: 'insertDocument :: caused by :: 11000 E11000 duplicate key error index: SSR.articles.$urlslug_1 dup key: { : "article-1" }' }
error: [routes/articles.js] Internal error(500): insertDocument :: caused by :: 11000 E11000 duplicate key error index: SSR.articles.$urlslug_1 dup key: { : "article-1" }
Is uniqueness no explict to validation in Mongoose? If not, how can I check if something already exists (roll my own unique validator) with Mongoose's validate()
method?
Upvotes: 0
Views: 803
Reputation: 311835
You can create your own custom validator to check for duplication, but you'd still need to handle the E11000 duplicate key error case as another insert could still occur in between the validation and insertion. So it's typically better to just use the E11000 error so your duplicate error handling is in just one spot.
You can use an approach like:
article.save(function (err) {
if (!err) {
log.info("article created");
return res.send({ status: 'OK', article:article });
} else {
console.log(err);
if(err.name == 'ValidationError') {
res.statusCode = 400;
res.send({ error: 'Validation error' });
} else if (err.name == 'MongoError' && err.code == 11000) {
res.statusCode = 400;
res.send({ error: 'Duplicate validation error' });
} else {
res.statusCode = 500;
res.send({ error: 'Server error' });
}
log.error('Internal error(%d): %s',res.statusCode,err.message);
}
});
Upvotes: 2