2017-02-01 48 views
0

所以我试图在我的Report文档和我的Station.reports子文档中更新字段status,这是一个对象数组,在一个API调用中。问题是我能够在进行API调用时更新报告文档,但不能更新工作站文档。通话结束后,console.log(station.reports);返回预期的子文档,即:[{"_id":"588fed278b50cd180bd6cc15","date":"2017-01-31T01:48:57.487Z","status":"Archived"}]但是,这并未保存在我的数据库中相应的Station文档中。请在这里获得帮助。谢谢。如何使用Mongoose同时更新两个独立的嵌入式文档?

站文档:

{ 
    "_id": "588a777d4e26720e7afa7e1e", 
    "phone": "(007) – 007 – 7007", 
    "name": "name1", 
    "email": "[email protected]", 
    "reports": [ 
     { 
     "status": "Submitted", 
     "date": "2014-01-31T01:48:57.487Z", 
     "_id": "588fed278b50cd180bd6cc15" 
     } 
    ] 
} 

报告文件

{ 
    "_id": "588fed278b50cd180bd6cc15", 
    "description": "Description of the report", 
    "time": "05:48 PM", 
    "date": "2017-01-31T01:48:57.487Z", 
    "status": "Archived", 
    "location" : "123 Main Street" 
    "station" : "588a777d4e26720e7afa7e1e" 
} 

API调用

router.put('/reports/:id/updateStatus', function (req, res) { 

    Report.findById(req.params.id, function(err,report){ 
     // if there is an error retrieving, send the error. 
     // nothing after res.send(err) will execute 
     if (err) 
      return res.send(err); 

     // Update the Report object 
     report.status = req.body.status; 

     // Update the Corresponding station.reports subdocument 
     Station.findOne({_id:report.station}, function (err, data) { 
      if(err) return console.log(err); 

      data.reports.forEach(function(rpt){ 
       if (rpt._id == req.params.id){ 

        rpt.status = req.body.status 
        data.save(function (err, station) { 
         if (err) 
          return res.send(err); 

         console.log(station.reports); 
        }) 
       } 
      }) 
     }) 

     report.save(function (err, report) { 
      if (err) 
       return res.send(err); 

      res.json(report); 
     }) 
    }); 
}) 

回答

0

经过多次尝试,并在Ravi的帮助下,我找到了一个能够帮助我工作的解决方案。唯一改变的是我的API电话。其余的代码没有改变。
希望这可以帮助有类似需求的人。

API调用

router.put('/reports/:id/updateStatus', function (req, res) { 

    Report.findById(req.params.id, function(err,report){ 
     // if there is an error retrieving, send the error. 
     // nothing after res.send(err) will execute 
     if (err) 
      return res.send(err); 

     // Update the Report object 
     report.status = req.body.status; 

     // Update the Corresponding station.reports subdocument 
     Station.findOne({_id:report.station}, function (err, info) { 
      if(err) return console.log(err); 

      info.reports.forEach(function(rpt){ 
       if (rpt._id == req.params.id){ 

        Station.update({_id:info._id, "reports._id":rpt._id }, 
         { 
          $set:{"reports.$.status": req.body.status } 
         },function (err, results) { 
          if(err) return console.log("This Station couldn't be updated " + err); 
          console.log(results) 
         } 
        ) 
       } 
      }) 
      report.save(function (err, report) { 
       if (err) 
        return res.send(err); 

       res.json({report:report, station:info}); 
      }); 
     }) 
    }); 
}) 
0

你正在做错误w ^更新station对象。使用findOneAndUpdate查找匹配的Station文档,然后更改匹配报表项的状态(使用reports._id进行匹配)。

试试这个:

Station.findOneAndUpdate({ 
     _id:report.station,"reports._id":req.params.id 
    },{ 
     $set : {reports.$.status : req.body.status} 
    },function(err){ 
    if(err) 
     return res.send(err); 
}); 

report._id会发现数组元素,其_idreq.params.idreport.$.status将只更新数组的匹配元素。

有关positional $(update) operator的详细信息,请参阅mongoDB positional Documentation

此外,我会建议savereport对象在callback of update。由于nodejsasynchronous,如果您在回调之外保存report,它将不会等待update完成。并且,您可能会收到在发送邮件后无法设置标题error。因此,建议在回调中做。

因此您最终API代码看起来像:

router.put('/reports/:id/updateStatus', function (req, res) { 

    Report.findById(req.params.id, function(err,report){ 
     // if there is an error retrieving, send the error. 
     // nothing after res.send(err) will execute 
     if (err) 
      return res.send(err); 

     // Update the Report object 
     report.status = req.body.status; 

     // Update the Corresponding station.reports subdocument 
     Station.findOneAndUpdate({ 
       "_id":report.station,"reports._id":req.params.id 
      },{ 
       $set : {"reports.$.status" : req.body.status} 
      },function(err, result){ 
       if(err) 
        return res.send(err); 
       console.log(result); 
       report.save(function (err, report) { 
        if (err) 
         return res.send(err); 

        res.json(report); 
       }); 
     }); 
    }); 
}) 

UPDATE 备用方法

另一种方法就可以了,你可以在原来的方式进行,但不要”将数据保存在forEach中,而是保存数据表forEach完成。

Station.findOne({_id:report.station}, function (err, data) { 
    if(err) return console.log(err); 

    data.reports.forEach(function(rpt){ 
     if (rpt._id == req.params.id){ 

      rpt.status = req.body.status 
     } 
    }); 
    data.save(function (err, station) { 
     if (err) 
      return res.send(err); 

     console.log(station.reports); 
     report.save(function (err, report) { 
      if (err) 
       return res.send(err); 
      res.json(report); 
     }); 
    }) 
}) 

希望这有助于!

+0

@Ravi嗨。感谢您的回复。我想尝试一下你的建议,但首先考虑到子文档'reports'是一个数组,你怎么可能写''reports._id“'。这可能会破坏整个事情吗?也许我错过了一些东西 – AllJs

+0

不,不能,你可以像这样在数组中查询,'reports。$。status'将只更新报告数组的匹配元素 –

+0

真的。我并不知道这种技术。好。现在让我试试看。 – AllJs

相关问题