mongoose 当插入一个违反唯一索引的MongoDB文档时,如何捕捉错误?

rqdpfwrv  于 2022-11-13  发布在  Go
关注(0)|答案(6)|浏览(284)

我正在开发一个MeAN应用程序。
这是我的用户名方案,用户名应该是唯一的。

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

module.exports = mongoose.model('User', new Schema({ 
    username: { type: String, unique: true }
}));

在我的发布路线上,我这样保存用户:

app.post('/authenticate', function(req, res) {
        var user = new User({
            username: req.body.username
        });

        user.save(function(err) {
            if (err) throw err;

            res.json({
                success: true
            });

        });
    })

如果我再次使用相同的用户名发帖,我会收到此错误:
Mongo错误:插入文档::原因:11000 E11000重复键错误索引:
有人能解释一下如何发送{ succes: false, message: 'User already exist!' }这样的json来代替错误吗
注:我发布用户后,我会自动验证,不需要密码或其他东西。

cqoc49vn

cqoc49vn1#

您将需要测试保存方法返回的错误,以查看是否因重复的用户名而引发该错误。

app.post('/authenticate', function(req, res) {
  var user = new User({
    username: req.body.username
  });

  user.save(function(err) {
    if (err) {
      if (err.name === 'MongoError' && err.code === 11000) {
        // Duplicate username
        return res.status(422).send({ succes: false, message: 'User already exist!' });
      }

      // Some other error
      return res.status(422).send(err);
    }

    res.json({
      success: true
    });

  });
})
wpx232ag

wpx232ag2#

您还可以尝试这个不错的包**mongoose-unique-validator**,它使错误处理变得更加容易,因为当您试图违反唯一约束时,将得到Mongoose验证错误,而不是MongoDB的E11000错误:

var mongoose = require('mongoose');
var uniqueValidator = require('mongoose-unique-validator');

// Define your schema as normal.
var userSchema = mongoose.Schema({
    username: { type: String, required: true, unique: true }
});

// You can pass through a custom error message as part of the optional options argument:
userSchema.plugin(uniqueValidator, { message: '{PATH} already exists!' });
kx7yvsdv

kx7yvsdv3#

2022年更新。看起来err.name发生了变化。以前,这个错误是作为MongoError返回的,但现在它是MongoServerError。有一个完整的故事是关于Mongoose不直接处理MongoError,基本上当一个ServerError出现时,mongoose会原样返回它。
注意:违反约束将在保存时从MongoDB返回E11000错误,而不是Mongoose验证错误。##标题##
但是现在,这个错误不再是MongoError,而是MongoServerError,它扩展了MongoErrorhttps://mongodb.github.io/node-mongodb-native/4.0/classes/mongoerror.html
这里有两个工作示例:
第一个

pnwntuvh

pnwntuvh4#

下面是使用类型错误而不是字符串来验证它的方法:

// your own error in a diff file
class UniqueError extends Error {
  constructor(message) {
    super(message)
  }
}

// in your service file
const { MongoError } = require('mongodb')

class UserService {
  async createUser(userJSON) {
    try {
      return await User.create(userJSON)
    } catch (e) {
      if (e instanceof MongoError && e.code === 11000) {
        throw new UniqueError('Username already exist')
      }
      throw e
    }
  }
}

// in your controller file
class UserController {
  async create(req, res) {
    const userJSON = req.body
    try {
      return res.status(201).json(await userService.createUser(userJSON))
    } catch (e) {
      if (e instanceof UniqueError) {
        return res.status(422).json({ message: e.message })
      }
      return res.status(500).json({ message: e.message })
    }
  }
}
zynd9foi

zynd9foi5#

如果您使用的是mongoose〉4.5.0,您可以根据他们的文档使用这个错误处理中间件:https://mongoosejs.com/docs/middleware.html#error-handling-middleware

//Checking for unique keys when you have multiple indexes
UserSchema.post("save", function (error, doc, next) {
  if (error.name === "MongoServerError" && error.code === 11000) {
    const keyPattern = Object.keys(error.keyPattern);
    const key = keyPattern[0];
    next(new Error(`${key} already taken!`));
  } else {
    next();
  }
});
t1qtbnec

t1qtbnec6#

试试看:

app.post('/authenticate', function(req, res) {
        var user = new User({
            username: req.body.username
        });

        user.save(function(err) {
            if (err) {
                // you could avoid http status if you want. I put error 500 
                return res.status(500).send({
                    success: false,
                    message: 'User already exist!'
                });
            }

            res.json({
                success: true
            });

        });
    })

相关问题