因此,我尝试在一个API调用中更新status
文档和我的Report
子文档中的字段Station.reports
,该子文档是一个对象数组。问题是我能够在进行API调用时更新报告文档,但不能更新工作站文档。在调用之后,console.log(station.reports);
返回预期的子文档:[{"_id":"588fed278b50cd180bd6cc15","date":"2017-01-31T01:48:57.487Z","status":"Archived"}]
但是这不会保存在我的数据库中的相应Station文档中。我在这里需要帮助。感谢。
电台文件:
{
"_id": "588a777d4e26720e7afa7e1e",
"phone": "(007) – 007 – 7007",
"name": "name1",
"email": "name1@email.com",
"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 :(得分:0)
更新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
会找到_id
为req.params.id
且report.$.status
的数组元素,只会更新数组的匹配元素。
有关positional $(update) operator
的详情,请阅读mongoDB positional Documentation。
此外,我建议save
report
callback of update
对象。由于nodejs
为asynchronous
,如果您将update
保存在回调之外,则不会等待report
完成。并且,您可能会在发送 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);
});
});
});
})
<强>更新强> 替代方法
另一种方法是,您可以按原始方式继续,但不要将数据保存在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);
});
})
})
希望这有帮助!
答案 1 :(得分:0)
经过多次尝试,并在Ravi的帮助下,我能够找到一个对我有用的解决方案。唯一改变的是我的API
电话。其余的代码没有改变
希望这有助于有类似需求的人。
API CALL
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});
});
})
});
})