Mongoose唯一验证器触发服务器错误

时间:2015-01-30 23:11:37

标签: node.js mongodb validation mongoose

我有slug属性,我设置为与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;
});

我将其成功发布到数据库,如下所示:

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');
}
});

当我尝试再次使用相同的slug,并且理想情况下会触发验证错误时,我收到服务器错误,而不是验证错误:

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"
}

(从我的节点控制台输出):

{ [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" }

Mongoose中的验证是否具有唯一性?如果没有,我如何使用Mongoose的validate()方法检查某些内容是否已存在(使用我自己的唯一验证器)?

1 个答案:

答案 0 :(得分:1)

您可以创建自己的custom validator来检查重复,但是您仍然需要处理E11000重复键错误情况,因为在验证和插入之间仍然会发生另一个插入。因此,通常最好只使用E11000错误,因此您的重复错误处理只在一个位置。

您可以使用以下方法:

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);
    }
});