2017-02-01 50 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

相關問題