Mongo .save() 在本地工作但在 Heroku 远程上有验证错误
Mongo .save() works locally but has validation errors on Heroku remote
我能够连接到我的 Mongo 数据库和我的数据,save() 在本地工作但自从推送到 Heroku 后我注意到保存触发验证错误。任何地方的日志中都没有任何内容。我有两个 post 路由调用 mongoose 保存函数,我在第二个函数中测试了 vs findOneAndUpdate
以排除这种情况,但验证错误仍然存在。我还尝试用我的中间件保护 post 路由,但仍然没有成功。我知道我会在编辑时遇到错误,在渲染时未定义字段,但保存函数仍应保存到另一个函数中的数据库中。
唯一显着的变化是集成了 auth0,所以我想也许我需要 运行 通过中间件的 post 路由,但这似乎也不起作用。
有效负载似乎已发送但未保存到数据库,关于如何获取更多信息或我可能遗漏的信息有什么建议吗?我知道有很多东西需要消化,但有什么想法吗?
- auth0 租户设置为生产
- mongo:ip 已列入白名单且 0.0.0.0 并且用户具有所有权限的读写权限 - 我也尝试过管理员
- mongo 数据库字符串格式:mongodb+srv://xxx:xxx@xxxxx-zylbs.azure.mongodb.net/bookingsDB?retryWrites=true&w=majority
- 集群中有两个数据库,每个数据库都有其唯一名称但集合名称相同,因此我可以引用 deva dn 生产数据库(以防万一)。
postroutes.js
const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
const Booking = mongoose.model('Booking');
router.post('/add', /* secured(), */(req, res) => {
insertRecord(req, res);
});
function insertRecord(req, res) {
const booking = new Booking();
booking.firstName = req.body.firstName;
booking.lastName = req.body.lastName;
booking.customerEmail = req.body.customerEmail;
booking.phone = req.body.phone;
booking.pax = req.body.pax;
booking.tourType = req.body.tourType;
booking.operatorName = req.body.operatorName;
booking.dateBooked = req.body.dateBooked;
booking.tourDate = req.body.tourDate;
booking.pickupAddress = req.body.pickupAddress;
booking.notes = req.body.notes;
booking.paidStatus = req.body.paidStatus;
booking.guidesName = req.body.guidesName;
booking.guidesEmail = req.body.guidesEmail;
booking.clientReminderSent = req.body.clientReminderSent;
booking.bookingCreatedSent = req.body.bookingCreatedSent;
booking.calendarEventCreated = req.body.calendarEventCreated;
booking.remindGoCapeGuides = req.body.remindGoCapeGuides;
booking.remindOperators = req.body.remindOperators;
booking.feedbackSent = req.body.feedbackSent;
booking.save((err, doc) => {
if (!err) {
// res.redirect('/list');
res.render('add', {
viewTitle: 'Add New Booking',
booking: req.body,
saveSuccessful: 'Booking Saved',
});
console.log('Saved!');
} else {
if (err.name == 'ValidationError') {
handleValidationError(err, req.body);
res.render('add', {
viewTitle: 'Add New Booking',
booking: req.body,
saveUnsuccessful: 'Not Saved: ' + err + ' Error saving booking, please try again.',
});
} else {
console.log('Error during record insertion : ' + err);
}
}
});
}
router.post('/edit', (req, res) => {
console.log(req.body._id);
updateRecord(req, res);
});
function updateRecord(req, res) {
const booking = new Booking();
booking.firstName = req.body.firstName;
booking.lastName = req.body.lastName;
booking.customerEmail = req.body.customerEmail;
booking.phone = req.body.phone;
booking.pax = req.body.pax;
booking.tourType = req.body.tourType;
booking.operatorName = req.body.operatorName;
booking.dateBooked = req.body.dateBooked;
booking.tourDate = req.body.tourDate;
booking.pickupAddress = req.body.pickupAddress;
booking.notes = req.body.notes;
booking.paidStatus = req.body.paidStatus;
booking.guidesName = req.body.guidesName;
booking.guidesEmail = req.body.guidesEmail;
booking.clientReminderSent = req.body.clientReminderSent;
booking.bookingCreatedSent = req.body.bookingCreatedSent;
booking.calendarEventCreated = req.body.calendarEventCreated;
booking.remindGoCapeGuides = req.body.remindGoCapeGuides;
booking.remindOperators = req.body.remindOperators;
booking.feedbackSent = req.body.feedbackSent;
Booking.findOneAndUpdate({_id: req.body._id}, req.body, {new: true}, (err, doc) => {
if (!err) {
res.redirect('/list');
/* res.render('edit', {
viewTitle: 'Edit Booking',
booking: req.body,
saveSuccessful: 'Booking Updated',
});*/
} else {
if (err.name == 'ValidationError') {
handleValidationError(err, req.body);
res.render('edit', {
viewTitle: 'Edit Booking',
booking: req.body,
saveUnsuccessful: 'Not Saved: Error saving booking, please try again.',
});
} else {
console.log('Error during record update : ' + err);
}
}
});
}
function handleValidationError(err, body) {
// eslint-disable-next-line guard-for-in
for (field in err.errors) {
switch (err.errors[field].path) {
case 'firstName':
body['firstNameError'] = err.errors[field].message;
break;
case 'lastName':
body['lastNameError'] = err.errors[field].message;
break;
case 'tourType':
body['tourTypeError'] = err.errors[field].message;
break;
case 'dateBooked':
body['dateBookedError'] = err.errors[field].message;
break;
case 'tourDate':
body['tourDateError'] = err.errors[field].message;
break;
case 'pax':
body['paxError'] = err.errors[field].message;
break;
case 'phone':
body['phoneError'] = err.errors[field].message;
break;
case 'customerEmail':
body['customerEmailError'] = err.errors[field].message;
break;
case 'pickupAddress':
body['pickupAddressError'] = err.errors[field].message;
break;
case 'operatorName':
body['operatorNameError'] = err.errors[field].message;
break;
case 'paidStatus':
body['paidStatusError'] = err.errors[field].message;
break;
case 'notes':
body['paidStatusError'] = err.errors[field].message;
break;
default:
break;
}
}
}
router.post('/search/:q', function (req, res) {
const q = req.body.q;
res.send(q);
console.log(q);
});
module.exports = router;
routes.js
router.get('/add', secured(), (req, res, next) => {
// const {_raw, _json, ...userProfile} = req.user;
res.render('add', {
viewTitle: 'Add New Booking',
booking: req.body,
});
});
router.get('/edit/:id', secured(), (req, res) => {
Booking.findById(req.params.id, (err, doc) => {
if (!err) {
res.render('edit', {
viewTitle: 'Edit Booking',
booking: doc,
});
}
});
});
model.js
const mongoose = require('mongoose');
const bookingSchema = new mongoose.Schema({
firstName: {
type: String,
required: 'This field is required',
},
lastName: {
type: String,
required: 'This field is required',
},
tourType: {
type: String,
required: 'This field is required',
},
dateBooked: {
type: String,
required: 'This field is required',
},
tourDate: {
type: String,
required: 'This field is required',
},
pax: {
type: String,
required: 'This field is required',
},
phone: {
type: String,
required: 'This field is required',
},
customerEmail: {
type: String,
required: 'This field is required',
},
pickupAddress: {
type: String,
required: 'This field is required',
},
operatorName: {
type: String,
required: 'This field is required',
},
paidStatus: {
type: String,
required: 'This field is required',
},
notes: {
type: String,
},
guidesName: {
type: String,
},
guidesEmail: {
type: String,
},
bookingCreatedSent: {
type: Boolean,
},
calendarEventCreated: {
type: Boolean,
},
clientReminderSent: {
type: Boolean,
},
remindOperators: {
type: Boolean,
},
remindGoCapeGuides: {
type: Boolean,
},
feedbackSent: {
type: Boolean,
},
});
// Custom validation for email
bookingSchema.path('customerEmail').validate((val) => {
emailRegex = /^(([^<>()\[\]\.,;:\s@"]+(\.[^<>()\[\]\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return emailRegex.test(val);
}, 'Invalid e-mail.');
mongoose.model('Booking', bookingSchema);
如有任何建议,我们将不胜感激!
更新
我添加了 mongoose.set('debug', true);
以获取更多信息,但是当我 post 一个表单时,我在 Heroku 日志或其他任何地方都看不到任何内容,这可能是中间件吗?由于路由 /add 和 /edit 正在通过安全中间件,post 路由是否应该做同样的事情?
好的,在 body-parser
和 express.json
之间切换进行测试时,我终于在日志中发现了一个错误,它导致我在另一个模块中出错,该模块没有被正确调用,但是依赖于保存,然后由于不正确的关闭和引用,它被挂起。看来现在一切都按预期再次工作。
在 body-parser 和 express.json 之间切换进行测试时,我终于在日志中发现错误,这导致我在另一个模块中出错,该模块未被正确调用但依赖于保存,然后由于不正确的关闭和引用,它被挂起。看来现在一切都按预期重新工作了。
我能够连接到我的 Mongo 数据库和我的数据,save() 在本地工作但自从推送到 Heroku 后我注意到保存触发验证错误。任何地方的日志中都没有任何内容。我有两个 post 路由调用 mongoose 保存函数,我在第二个函数中测试了 vs findOneAndUpdate
以排除这种情况,但验证错误仍然存在。我还尝试用我的中间件保护 post 路由,但仍然没有成功。我知道我会在编辑时遇到错误,在渲染时未定义字段,但保存函数仍应保存到另一个函数中的数据库中。
唯一显着的变化是集成了 auth0,所以我想也许我需要 运行 通过中间件的 post 路由,但这似乎也不起作用。
有效负载似乎已发送但未保存到数据库,关于如何获取更多信息或我可能遗漏的信息有什么建议吗?我知道有很多东西需要消化,但有什么想法吗?
- auth0 租户设置为生产
- mongo:ip 已列入白名单且 0.0.0.0 并且用户具有所有权限的读写权限 - 我也尝试过管理员
- mongo 数据库字符串格式:mongodb+srv://xxx:xxx@xxxxx-zylbs.azure.mongodb.net/bookingsDB?retryWrites=true&w=majority
- 集群中有两个数据库,每个数据库都有其唯一名称但集合名称相同,因此我可以引用 deva dn 生产数据库(以防万一)。
postroutes.js
const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
const Booking = mongoose.model('Booking');
router.post('/add', /* secured(), */(req, res) => {
insertRecord(req, res);
});
function insertRecord(req, res) {
const booking = new Booking();
booking.firstName = req.body.firstName;
booking.lastName = req.body.lastName;
booking.customerEmail = req.body.customerEmail;
booking.phone = req.body.phone;
booking.pax = req.body.pax;
booking.tourType = req.body.tourType;
booking.operatorName = req.body.operatorName;
booking.dateBooked = req.body.dateBooked;
booking.tourDate = req.body.tourDate;
booking.pickupAddress = req.body.pickupAddress;
booking.notes = req.body.notes;
booking.paidStatus = req.body.paidStatus;
booking.guidesName = req.body.guidesName;
booking.guidesEmail = req.body.guidesEmail;
booking.clientReminderSent = req.body.clientReminderSent;
booking.bookingCreatedSent = req.body.bookingCreatedSent;
booking.calendarEventCreated = req.body.calendarEventCreated;
booking.remindGoCapeGuides = req.body.remindGoCapeGuides;
booking.remindOperators = req.body.remindOperators;
booking.feedbackSent = req.body.feedbackSent;
booking.save((err, doc) => {
if (!err) {
// res.redirect('/list');
res.render('add', {
viewTitle: 'Add New Booking',
booking: req.body,
saveSuccessful: 'Booking Saved',
});
console.log('Saved!');
} else {
if (err.name == 'ValidationError') {
handleValidationError(err, req.body);
res.render('add', {
viewTitle: 'Add New Booking',
booking: req.body,
saveUnsuccessful: 'Not Saved: ' + err + ' Error saving booking, please try again.',
});
} else {
console.log('Error during record insertion : ' + err);
}
}
});
}
router.post('/edit', (req, res) => {
console.log(req.body._id);
updateRecord(req, res);
});
function updateRecord(req, res) {
const booking = new Booking();
booking.firstName = req.body.firstName;
booking.lastName = req.body.lastName;
booking.customerEmail = req.body.customerEmail;
booking.phone = req.body.phone;
booking.pax = req.body.pax;
booking.tourType = req.body.tourType;
booking.operatorName = req.body.operatorName;
booking.dateBooked = req.body.dateBooked;
booking.tourDate = req.body.tourDate;
booking.pickupAddress = req.body.pickupAddress;
booking.notes = req.body.notes;
booking.paidStatus = req.body.paidStatus;
booking.guidesName = req.body.guidesName;
booking.guidesEmail = req.body.guidesEmail;
booking.clientReminderSent = req.body.clientReminderSent;
booking.bookingCreatedSent = req.body.bookingCreatedSent;
booking.calendarEventCreated = req.body.calendarEventCreated;
booking.remindGoCapeGuides = req.body.remindGoCapeGuides;
booking.remindOperators = req.body.remindOperators;
booking.feedbackSent = req.body.feedbackSent;
Booking.findOneAndUpdate({_id: req.body._id}, req.body, {new: true}, (err, doc) => {
if (!err) {
res.redirect('/list');
/* res.render('edit', {
viewTitle: 'Edit Booking',
booking: req.body,
saveSuccessful: 'Booking Updated',
});*/
} else {
if (err.name == 'ValidationError') {
handleValidationError(err, req.body);
res.render('edit', {
viewTitle: 'Edit Booking',
booking: req.body,
saveUnsuccessful: 'Not Saved: Error saving booking, please try again.',
});
} else {
console.log('Error during record update : ' + err);
}
}
});
}
function handleValidationError(err, body) {
// eslint-disable-next-line guard-for-in
for (field in err.errors) {
switch (err.errors[field].path) {
case 'firstName':
body['firstNameError'] = err.errors[field].message;
break;
case 'lastName':
body['lastNameError'] = err.errors[field].message;
break;
case 'tourType':
body['tourTypeError'] = err.errors[field].message;
break;
case 'dateBooked':
body['dateBookedError'] = err.errors[field].message;
break;
case 'tourDate':
body['tourDateError'] = err.errors[field].message;
break;
case 'pax':
body['paxError'] = err.errors[field].message;
break;
case 'phone':
body['phoneError'] = err.errors[field].message;
break;
case 'customerEmail':
body['customerEmailError'] = err.errors[field].message;
break;
case 'pickupAddress':
body['pickupAddressError'] = err.errors[field].message;
break;
case 'operatorName':
body['operatorNameError'] = err.errors[field].message;
break;
case 'paidStatus':
body['paidStatusError'] = err.errors[field].message;
break;
case 'notes':
body['paidStatusError'] = err.errors[field].message;
break;
default:
break;
}
}
}
router.post('/search/:q', function (req, res) {
const q = req.body.q;
res.send(q);
console.log(q);
});
module.exports = router;
routes.js
router.get('/add', secured(), (req, res, next) => {
// const {_raw, _json, ...userProfile} = req.user;
res.render('add', {
viewTitle: 'Add New Booking',
booking: req.body,
});
});
router.get('/edit/:id', secured(), (req, res) => {
Booking.findById(req.params.id, (err, doc) => {
if (!err) {
res.render('edit', {
viewTitle: 'Edit Booking',
booking: doc,
});
}
});
});
model.js
const mongoose = require('mongoose');
const bookingSchema = new mongoose.Schema({
firstName: {
type: String,
required: 'This field is required',
},
lastName: {
type: String,
required: 'This field is required',
},
tourType: {
type: String,
required: 'This field is required',
},
dateBooked: {
type: String,
required: 'This field is required',
},
tourDate: {
type: String,
required: 'This field is required',
},
pax: {
type: String,
required: 'This field is required',
},
phone: {
type: String,
required: 'This field is required',
},
customerEmail: {
type: String,
required: 'This field is required',
},
pickupAddress: {
type: String,
required: 'This field is required',
},
operatorName: {
type: String,
required: 'This field is required',
},
paidStatus: {
type: String,
required: 'This field is required',
},
notes: {
type: String,
},
guidesName: {
type: String,
},
guidesEmail: {
type: String,
},
bookingCreatedSent: {
type: Boolean,
},
calendarEventCreated: {
type: Boolean,
},
clientReminderSent: {
type: Boolean,
},
remindOperators: {
type: Boolean,
},
remindGoCapeGuides: {
type: Boolean,
},
feedbackSent: {
type: Boolean,
},
});
// Custom validation for email
bookingSchema.path('customerEmail').validate((val) => {
emailRegex = /^(([^<>()\[\]\.,;:\s@"]+(\.[^<>()\[\]\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return emailRegex.test(val);
}, 'Invalid e-mail.');
mongoose.model('Booking', bookingSchema);
如有任何建议,我们将不胜感激!
更新
我添加了 mongoose.set('debug', true);
以获取更多信息,但是当我 post 一个表单时,我在 Heroku 日志或其他任何地方都看不到任何内容,这可能是中间件吗?由于路由 /add 和 /edit 正在通过安全中间件,post 路由是否应该做同样的事情?
好的,在 body-parser
和 express.json
之间切换进行测试时,我终于在日志中发现了一个错误,它导致我在另一个模块中出错,该模块没有被正确调用,但是依赖于保存,然后由于不正确的关闭和引用,它被挂起。看来现在一切都按预期再次工作。
在 body-parser 和 express.json 之间切换进行测试时,我终于在日志中发现错误,这导致我在另一个模块中出错,该模块未被正确调用但依赖于保存,然后由于不正确的关闭和引用,它被挂起。看来现在一切都按预期重新工作了。