猫鼬保存:文档验证失败,但 console.log 并接受手动插入
Mongoose Save: Document failed validation, but console.log and manual insert is accepted
我正在处理一些注册代码(MERN 堆栈),并且在使用 user.save 时从 MongoDB 收到“文档验证失败”。但是,如果我使用 console.log(),copy/paste 结果插入,并将单引号替换为双引号,则可以接受。
到目前为止,这是我的注册路线:
router.post("/signup", async (req, res) => {
let { firstName,
lastName,
profileImage,
email,
subscribed_Comments,
subscribed_NewPost,
username,
password } = req.body;
if (username && email && password && firstName && lastName && subscribed_Comments !== undefined && subscribed_NewPost !== undefined) {
username = username.toLowerCase();
email = email.toLowerCase();
//Validate Password
if (/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,15}$/.test(password)) {
//Check if username or email already used
User.findOne({ "$or": [{ "username": username }, { "email": email }] })
.exec((err, user) => {
if (err) {
console.error(err);
res.status(500).send({ "error": "An unexpected error occurred. Please contact an administrator." });
} else if (user === null) {
//User did not exist ... create
bcrypt.genSalt(Number(SALT), function (err, salt) {
if (err) {
console.error(err);
res.status(500).send({ "error": "An unexpected error occurred. Please contact an administrator." });
}
bcrypt.hash(password, salt, function (err, hash) {
if (err) {
console.error(err);
res.status(500).send({ "error": "An unexpected error occurred. Please contact an administrator." });
}
//create user
let user = new User({
username: username,
email: email,
password: hash,
userRole: "User"
});
console.log(user)
user.save((err, user) => {
if (err) {
console.error(err);
res.status(500).send({ "error": "Failed to create a User. Please contact an administrator." });
} else {
console.log(`Successfully created user ${user.username}`);
//create account
let account = new Account({
"FirstName": firstName,
"LastName": lastName,
"SubscribedNewPost": subscribed_NewPost,
"SubscribedComments": subscribed_Comments,
"ProfileImage": profileImage || "",
"User_Account": user._id
});
account.save((err, account) => {
if (err) {
console.error(err);
user.delete();
res.status(500).send({ "error": "Failed to create an Account. Please contact an Administrator" });
} else {
console.log(`Successfully created account for ${account.firstName} ${account.lastName}`);
req.session.userid = user._id;
req.session.username = user.username;
req.session.userRole = user.userRole;
}
})
}
});
});
});
} else {
console.log(`Username: ${username} or Email: ${email} already in use.`);
res.status(500).send({ "error": "Username or Email is already in use" });
}
});
} else {
// Invalid Password
console.log("Invalid Password in Signup");
res.status(500).send({ "error": "Password did not meet expected criteria" });
}
} else {
res.status(500).send({ "error": "Invalid Request" });
}
})
这是猫鼬模式
const mongoose = require("mongoose");
const userSchema = mongoose.Schema({
username: {
type: String,
unique: [true, "That username already registered."],
required: [true, "Username is required."]
},
email: {
type: String,
unique: [true, "That email is already registered."],
required: [true, "Email is required."],
validate: {
validator: function(v){
return /^\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,3}$/i.test(v);
},
message: "Email was not in a valid format."
}
},
password: {
type: String,
required: [true, "Password is required."]
},
userRole: {
type: String,
enum: ["Anonymous", "User", "Moderator"],
required: [true, "User Role is required."]
}
}, {collection: "User"}, {versionKey: false})
module.exports = mongoose.model("User",userSchema);
这是MongoDB验证
{
$jsonSchema: {
bsonType: 'object',
title: 'user',
required: [
'username',
'email',
'password',
'userRole'
],
properties: {
_id: {
bsonType: 'objectId',
uniqueItems: true
},
username: {
bsonType: 'string',
uniqueItems: true
},
email: {
bsonType: 'string',
uniqueItems: true,
pattern: '^\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,3}$'
},
password: {
bsonType: 'string'
},
userRole: {
'enum': [
'Anonymous',
'User',
'Moderator'
]
}
},
additionalProperties: false
}
}
这是验证失败的 json(来自 console.log())。如果我 copy/paste 这个并将单引号替换为双引号然后 mongodb 接受它。
{
_id: 606a0a09d70db426acda05ee,
username: 'johndoe',
email: 'johndoe@gmail.com',
password: 'b$vofYCj31690seAIKHqjkUuba8paeJy5ZC1Qt8ZHjZHmKVQurZ.hfi',
userRole: 'User'
}
关于上述内容在遵循我定义的架构时为什么会失败验证的任何想法?我已经尝试从 Mongoose 模式中删除验证以确保它不会在那里失败并且没有失败。我认为唯一剩下的可能是它没有_id 的格式,但是 mongodb 会拒绝 mongoose 创建的默认 _id 是没有意义的。
编辑:这是堆栈跟踪
MongoError: Document failed validation
at Function.create (D:\Projects\portfolio-backend\node_modules\mongodb\lib\core\error.js:57:12)
at toError (D:\Projects\portfolio-backend\node_modules\mongodb\lib\utils.js:123:22)
at D:\Projects\portfolio-backend\node_modules\mongodb\lib\operations\common_functions.js:265:39
at handler (D:\Projects\portfolio-backend\node_modules\mongodb\lib\core\sdam\topology.js:942:24)
at D:\Projects\portfolio-backend\node_modules\mongodb\lib\cmap\connection_pool.js:350:13
at handleOperationResult (D:\Projects\portfolio-backend\node_modules\mongodb\lib\core\sdam\server.js:558:5)
at MessageStream.messageHandler (D:\Projects\portfolio-backend\node_modules\mongodb\lib\cmap\connection.js:277:5)
at MessageStream.emit (events.js:310:20)
at processIncomingData (D:\Projects\portfolio-backend\node_modules\mongodb\lib\cmap\message_stream.js:144:12)
at MessageStream._write (D:\Projects\portfolio-backend\node_modules\mongodb\lib\cmap\message_stream.js:42:5)
at doWrite (_stream_writable.js:442:12)
at writeOrBuffer (_stream_writable.js:426:5)
at MessageStream.Writable.write (_stream_writable.js:317:11)
at Socket.ondata (_stream_readable.js:695:22)
at Socket.emit (events.js:310:20)
at addChunk (_stream_readable.js:286:12) {
driver: true,
name: 'MongoError',
index: 0,
code: 121
}
错误可能是因为_id
。您正在发送 ObjectId
的字符串表示形式,但 _id
所需的类型是 ObjectId
。尝试将 _id: 606a0a09d70db426acda05ee
替换为 _id:ObjectId('606a0a09d70db426acda05ee')
;
你也可以尝试改变这个:
let user = new User({
username: username,
email: email,
password: hash,
});
console.log(user)
user.save((err, user) => {
有了这个:
User.create({
username: username,
email: email,
password: hash,
}).then((user)=>{
console.log('User successfully created: ', user);
}, (error)=>{
console.log('ERROR: ', error);
})
所以,我想通了。显然,Mongoose Schema 将 __v 整数添加到 .save 调用中,尽管我在模式中有 versionKey: false 。我通过将验证设置为警告而不是错误来测试它,并观察到 __v 出现在已保存的文档中。为了修复它,我在 mongo.
中的验证 JSON 中添加了以下内容
__v: {
bsonType: 'int'
}
TLDR:缺少的“验证”是 __v 属性 未定义,而 'additionalProperties' 设置为 false。
我正在处理一些注册代码(MERN 堆栈),并且在使用 user.save 时从 MongoDB 收到“文档验证失败”。但是,如果我使用 console.log(),copy/paste 结果插入,并将单引号替换为双引号,则可以接受。
到目前为止,这是我的注册路线:
router.post("/signup", async (req, res) => {
let { firstName,
lastName,
profileImage,
email,
subscribed_Comments,
subscribed_NewPost,
username,
password } = req.body;
if (username && email && password && firstName && lastName && subscribed_Comments !== undefined && subscribed_NewPost !== undefined) {
username = username.toLowerCase();
email = email.toLowerCase();
//Validate Password
if (/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,15}$/.test(password)) {
//Check if username or email already used
User.findOne({ "$or": [{ "username": username }, { "email": email }] })
.exec((err, user) => {
if (err) {
console.error(err);
res.status(500).send({ "error": "An unexpected error occurred. Please contact an administrator." });
} else if (user === null) {
//User did not exist ... create
bcrypt.genSalt(Number(SALT), function (err, salt) {
if (err) {
console.error(err);
res.status(500).send({ "error": "An unexpected error occurred. Please contact an administrator." });
}
bcrypt.hash(password, salt, function (err, hash) {
if (err) {
console.error(err);
res.status(500).send({ "error": "An unexpected error occurred. Please contact an administrator." });
}
//create user
let user = new User({
username: username,
email: email,
password: hash,
userRole: "User"
});
console.log(user)
user.save((err, user) => {
if (err) {
console.error(err);
res.status(500).send({ "error": "Failed to create a User. Please contact an administrator." });
} else {
console.log(`Successfully created user ${user.username}`);
//create account
let account = new Account({
"FirstName": firstName,
"LastName": lastName,
"SubscribedNewPost": subscribed_NewPost,
"SubscribedComments": subscribed_Comments,
"ProfileImage": profileImage || "",
"User_Account": user._id
});
account.save((err, account) => {
if (err) {
console.error(err);
user.delete();
res.status(500).send({ "error": "Failed to create an Account. Please contact an Administrator" });
} else {
console.log(`Successfully created account for ${account.firstName} ${account.lastName}`);
req.session.userid = user._id;
req.session.username = user.username;
req.session.userRole = user.userRole;
}
})
}
});
});
});
} else {
console.log(`Username: ${username} or Email: ${email} already in use.`);
res.status(500).send({ "error": "Username or Email is already in use" });
}
});
} else {
// Invalid Password
console.log("Invalid Password in Signup");
res.status(500).send({ "error": "Password did not meet expected criteria" });
}
} else {
res.status(500).send({ "error": "Invalid Request" });
}
})
这是猫鼬模式
const mongoose = require("mongoose");
const userSchema = mongoose.Schema({
username: {
type: String,
unique: [true, "That username already registered."],
required: [true, "Username is required."]
},
email: {
type: String,
unique: [true, "That email is already registered."],
required: [true, "Email is required."],
validate: {
validator: function(v){
return /^\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,3}$/i.test(v);
},
message: "Email was not in a valid format."
}
},
password: {
type: String,
required: [true, "Password is required."]
},
userRole: {
type: String,
enum: ["Anonymous", "User", "Moderator"],
required: [true, "User Role is required."]
}
}, {collection: "User"}, {versionKey: false})
module.exports = mongoose.model("User",userSchema);
这是MongoDB验证
{
$jsonSchema: {
bsonType: 'object',
title: 'user',
required: [
'username',
'email',
'password',
'userRole'
],
properties: {
_id: {
bsonType: 'objectId',
uniqueItems: true
},
username: {
bsonType: 'string',
uniqueItems: true
},
email: {
bsonType: 'string',
uniqueItems: true,
pattern: '^\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,3}$'
},
password: {
bsonType: 'string'
},
userRole: {
'enum': [
'Anonymous',
'User',
'Moderator'
]
}
},
additionalProperties: false
}
}
这是验证失败的 json(来自 console.log())。如果我 copy/paste 这个并将单引号替换为双引号然后 mongodb 接受它。
{
_id: 606a0a09d70db426acda05ee,
username: 'johndoe',
email: 'johndoe@gmail.com',
password: 'b$vofYCj31690seAIKHqjkUuba8paeJy5ZC1Qt8ZHjZHmKVQurZ.hfi',
userRole: 'User'
}
关于上述内容在遵循我定义的架构时为什么会失败验证的任何想法?我已经尝试从 Mongoose 模式中删除验证以确保它不会在那里失败并且没有失败。我认为唯一剩下的可能是它没有_id 的格式,但是 mongodb 会拒绝 mongoose 创建的默认 _id 是没有意义的。
编辑:这是堆栈跟踪
MongoError: Document failed validation
at Function.create (D:\Projects\portfolio-backend\node_modules\mongodb\lib\core\error.js:57:12)
at toError (D:\Projects\portfolio-backend\node_modules\mongodb\lib\utils.js:123:22)
at D:\Projects\portfolio-backend\node_modules\mongodb\lib\operations\common_functions.js:265:39
at handler (D:\Projects\portfolio-backend\node_modules\mongodb\lib\core\sdam\topology.js:942:24)
at D:\Projects\portfolio-backend\node_modules\mongodb\lib\cmap\connection_pool.js:350:13
at handleOperationResult (D:\Projects\portfolio-backend\node_modules\mongodb\lib\core\sdam\server.js:558:5)
at MessageStream.messageHandler (D:\Projects\portfolio-backend\node_modules\mongodb\lib\cmap\connection.js:277:5)
at MessageStream.emit (events.js:310:20)
at processIncomingData (D:\Projects\portfolio-backend\node_modules\mongodb\lib\cmap\message_stream.js:144:12)
at MessageStream._write (D:\Projects\portfolio-backend\node_modules\mongodb\lib\cmap\message_stream.js:42:5)
at doWrite (_stream_writable.js:442:12)
at writeOrBuffer (_stream_writable.js:426:5)
at MessageStream.Writable.write (_stream_writable.js:317:11)
at Socket.ondata (_stream_readable.js:695:22)
at Socket.emit (events.js:310:20)
at addChunk (_stream_readable.js:286:12) {
driver: true,
name: 'MongoError',
index: 0,
code: 121
}
错误可能是因为_id
。您正在发送 ObjectId
的字符串表示形式,但 _id
所需的类型是 ObjectId
。尝试将 _id: 606a0a09d70db426acda05ee
替换为 _id:ObjectId('606a0a09d70db426acda05ee')
;
你也可以尝试改变这个:
let user = new User({
username: username,
email: email,
password: hash,
});
console.log(user)
user.save((err, user) => {
有了这个:
User.create({
username: username,
email: email,
password: hash,
}).then((user)=>{
console.log('User successfully created: ', user);
}, (error)=>{
console.log('ERROR: ', error);
})
所以,我想通了。显然,Mongoose Schema 将 __v 整数添加到 .save 调用中,尽管我在模式中有 versionKey: false 。我通过将验证设置为警告而不是错误来测试它,并观察到 __v 出现在已保存的文档中。为了修复它,我在 mongo.
中的验证 JSON 中添加了以下内容 __v: {
bsonType: 'int'
}
TLDR:缺少的“验证”是 __v 属性 未定义,而 'additionalProperties' 设置为 false。