我正尝试通过HTML表单使用findByIdAndUpdate
更新数据库,该表单适用于除嵌套数据(ePIMS
,codeVersion
和region
以外的所有更新)没问题)。当我执行console.log(req.body.environment.instance)
时,它会像正确输入一样输出我键入的数据,但是由于某些原因,mongoDB不会使用该信息进行更新。有人能弄清楚我在做什么错吗?
猫鼬模式:
var environmentSchema = new mongoose.Schema({
ePIMS: String,
codeVersion: String,
region: String,
/*instance and testEnv don't seem to update in the database*/
HCHC: {
instance: String,
testEnv: String
}
});
我正在更新的表单:
<form action="/environments/<%= environment._id %>?_method=PUT" method="POST">
<input class="form-control" type="text" name="environment[ePIMS]" placeholder="ePIMS" value="<%= environment.ePIMS %>" />
<input class="form-control" type="text" name="environment[region]" placeholder="Region" value="<%= environment.region %>" />
<input class="form-control" type="text" name="environment[instance]" placeholder="HCHC Instance" value="<%= environment.instance %>" />
<input class="form-control" type="text" name="environment[testEnv]" placeholder="Test Environment" value="<%= environment.testEnv %>" />
<button class="btn btn-primary">Submit</button>
</form>
编辑和更新路线:
//Edit environment route
router.get("/environments/:id/edit", function(req, res){
Environment.findById(req.params.id, function(err, foundEnvironment){
if(err){
res.redirect("/");
} else {
res.render("edit", {environment: foundEnvironment});
}
});
});
//Update environment route
router.put("/environments/:id", function(req, res){
Environment.findByIdAndUpdate(req.params.id, req.body.environment, function(err, updatedEnvironment){
if (err) {
res.redirect("/environments");
} else {
res.redirect("/environments");
//console.log(req.body.environment.instance)
}
});
});
更新:解决方案 谢谢Nayan的帮助!
我这样更改了更新路线:
//Update environment route
router.put("/environments/:id", function(req, res){
var data = {
HCHC : {
instance: req.body.instance,
testEnv: req.body.testEnv
}
}
Environment.findByIdAndUpdate(req.params.id, {$set: data}, function(err, updatedEnvironment){
if (err) {
res.redirect("/environments");
} else {
res.redirect("/environments");
}
});
});
答案 0 :(得分:3)
您要发送不同的主体结构,并直接在findOneAndUpdate()中进行设置,因此在结构不同的地方它无法正常工作。
您可以应用的可能解决方案是将请求的主体更改为如下所示:
"environment" : {
"ePIMS" : value,
"codeVersion" : value,
"region" : value,
"HCHC": {
"instance" : value,
"testEnv" : value
}
}
或者,您也可以根据需要将两个实例和testEnv放在HCHC中。
如果直接在函数中传递主体,则两种方法都请确保您具有相同的结构。
另一种解决方案
创建一个局部变量来修复结构并将其传递给函数,例如:
router.put("/environments/:id", function(req, res){
let body = req.body.environment
let bodyData = {
ePIMS: body.ePIMS,
codeVersion: body.codeVersion,
region: body.region,
HCHC: {
instance: body.instance,
testEnv: body.testEnv
}
}
Environment.findByIdAndUpdate(req.params.id, bodyData, function(err, updatedEnvironment){
if (err) {
res.redirect("/environments");
} else {
res.redirect("/environments");
//console.log(req.body.environment.instance)
}
});
});
答案 1 :(得分:1)
此解决方案对我有用:
router.patch('/tasks/:id', async (req,res)=>{
try{
const task= await Task.findByIdAndUpdate(req.params.id,req.body,{new:true,runValidators:true})
if(!task)
{
res.status(404).send()
}
res.send(task)
}
catch(e)
{
res.status(500).send()
}
})
但是,我最终的解决方案包括验证是在不使用findByIdAndUpdate的情况下增加更新:
router.patch('/tasks/:id', async (req,res)=>{
//validate update operation
const updates=Object.keys(req.body)
const allowedUpdates= ['description','completed']
const isInvalidOperation= updates.every((update)=>allowedUpdates.includes(update))
if(!isInvalidOperation)
{
return res.status(400).send({error:'invalid updates'})
}
try{
const task= await Task.findById(req.params.id)
updates.forEach((update)=>task[update]=req.body[update])
await task.save()
if(!task)
{
res.status(404).send()
}
res.send(task)
}
catch(e)
{
res.status(500).send()
}
})