插入违反唯一索引的 MongoDB 文档时如何捕获错误?
How to catch the error when inserting a MongoDB document which violates an unique index?
我正在构建一个 MEAN 应用程序。
这是我的用户名架构,用户名应该是唯一的。
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
module.exports = mongoose.model('User', new Schema({
username: { type: String, unique: true }
}));
在我的 post 路线上,我这样保存用户:
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
});
});
})
如果我再次使用相同的用户名post,我会得到这个错误:
MongoError: insertDocument :: caused by :: 11000 E11000 duplicate key
error index:
有人可以解释如何发送 json 之类的 { succes: false, message: 'User already exist!' }
而不是错误
注意:我post用户后我会自动认证,不需要密码或其他东西。
试试这个:
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
});
});
})
您也可以试试这个不错的包 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!' });
您需要测试从保存方法返回的错误,看看它是否因用户名重复而抛出。
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
});
});
})
以下是使用类型错误而不是字符串来验证它的方法:
// 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 Error('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 })
}
}
}
2022年更新。
看起来 err.name 已更改。之前,此错误 return 为 MongoError
,但现在为 MongoServerError
。有一个关于 Mongoose 不直接处理 MongoError
的完整故事,基本上当 ServerError 出现时 mongoose return 它是原样。
NOTE: violating the constraint returns an E11000 error from MongoDB when saving, not a Mongoose validation error.## Heading ##
但是现在,这个错误不再是 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
});
});
})
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 },
});
});
}
我正在构建一个 MEAN 应用程序。
这是我的用户名架构,用户名应该是唯一的。
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
module.exports = mongoose.model('User', new Schema({
username: { type: String, unique: true }
}));
在我的 post 路线上,我这样保存用户:
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
});
});
})
如果我再次使用相同的用户名post,我会得到这个错误:
MongoError: insertDocument :: caused by :: 11000 E11000 duplicate key error index:
有人可以解释如何发送 json 之类的 { succes: false, message: 'User already exist!' }
注意:我post用户后我会自动认证,不需要密码或其他东西。
试试这个:
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
});
});
})
您也可以试试这个不错的包 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!' });
您需要测试从保存方法返回的错误,看看它是否因用户名重复而抛出。
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
});
});
})
以下是使用类型错误而不是字符串来验证它的方法:
// 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 Error('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 })
}
}
}
2022年更新。
看起来 err.name 已更改。之前,此错误 return 为 MongoError
,但现在为 MongoServerError
。有一个关于 Mongoose 不直接处理 MongoError
的完整故事,基本上当 ServerError 出现时 mongoose return 它是原样。
NOTE: violating the constraint returns an E11000 error from MongoDB when saving, not a Mongoose validation error.## Heading ##
但是现在,这个错误不再是 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
});
});
})
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 },
});
});
}