猫鼬不使用findByIdAndUpdate更新数据库吗?

时间:2020-04-28 17:16:50

标签: javascript html node.js mongodb mongoose

我正尝试通过HTML表单使用findByIdAndUpdate更新数据库,该表单适用于除嵌套数据(ePIMScodeVersionregion以外的所有更新)没问题)。当我执行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");
    }
  });
});

2 个答案:

答案 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()
      }
  })