如何在插入违反唯一索引的MongoDB文档时捕获错误?

Hie*_*ero 17 javascript mean mongoose mongodb express

我正在构建一个MEAN应用程序.

这是我的用户名架构,用户名应该是唯一的.

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

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

在我的帖子路线上,我像这样保存用户:

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

        });
    })
Run Code Online (Sandbox Code Playgroud)

如果我再次使用相同的用户名发布,我会收到此错误:

MongoError:insertDocument ::由:: 11000引起的E11000重复键错误索引:

有人可以解释如何发送json而不是错误 { succes: false, message: 'User already exist!' }

注意:在我发布用户后,我将自动进行身份验证,不需要密码或其他内容.

Jas*_*ust 36

您将需要测试从save方法返回的错误,以查看是否为重复的用户名抛出了该错误.

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

  });
})
Run Code Online (Sandbox Code Playgroud)

  • 500 不应该用作状态代码,因为它不是内部服务器错误。所以数据冲突时可以使用400。 (2认同)
  • 如果文档中有两个唯一字段怎么办?如何给出明确的消息哪个字段导致错误。例如:我们可以让用户拥有电子邮件和别名字段,这两个字段都应该是唯一的? (2认同)

小智 7

2022 年更新。看起来 err.name 已更改。之前,此错误作为 a 返回MongoError,但现在它是 a MongoServerError。有一个关于 Mongoose 不MongoError直接处理的完整故事,基本上当 ServerError 出现时 mongoose 按原样返回它。

注意:违反约束会在保存时从 MongoDB 返回 E11000 错误,而不是 Mongoose 验证错误。## 标题 ##

但现在,这个错误不再是MongoError,而是MongoServerError现在,它扩展了MongoError https://mongodb.github.io/node-mongodb-native/4.0/classes/mongoerror.html

这里有两个工作示例:

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

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

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

    res.json({
      success: true
    });

  });
})
Run Code Online (Sandbox Code Playgroud)
async function store(req: Request, res: Response) {
    const { email, password }: IUser = req.body;

    const user: IUser = new User({
        email: email,
        password: await hashPassword(password),
    });

    user
        .save()
        .then(result => {
            return res.status(201).json({
                message: 'Successful registration.',
                data: { email: result.email },
            });
        })
        .catch(err => {    
            if (err.name === 'MongoServerError' && err.code === 11000) {
                //There was a duplicate key error
                return res.status(400).json({
                    message: 'Email already in use.',
                    data: { err },
                });
            }
            return res.status(400).json({
                message: "You didn't give us what we want!",
                data: { err },
            });
        });
}
Run Code Online (Sandbox Code Playgroud)


chr*_*dam 6

您还可以尝试使用这个不错的包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!' });
Run Code Online (Sandbox Code Playgroud)