[英]MongoDB - Mongoose: How Do I Update Simultaneously Two Separate Embedded Documents With Mongoose?
So I am trying to update the field status
in my Report
document and in my Station.reports
sub-document which is an array of objects, in one single API call. 因此,我试图通过一个API调用来更新
Report
文档和Station.reports
子文档中的字段status
,该子文档是一组对象。 The issue is that I am able to update the Report document, but not the station document when making the API call. 问题是在进行API调用时,我能够更新Report文档,但不能更新Station文档。 After the call, the
console.log(station.reports);
通话结束后,
console.log(station.reports);
returns the expected subdocument which is : [{"_id":"588fed278b50cd180bd6cc15","date":"2017-01-31T01:48:57.487Z","status":"Archived"}]
But this is not saved in the corresponding Station document in my DB. 返回期望的子文档:
[{"_id":"588fed278b50cd180bd6cc15","date":"2017-01-31T01:48:57.487Z","status":"Archived"}]
但这未保存在我的数据库中相应的Station文档。 Please I need help here. 请在这里我需要帮助。 Thanks.
谢谢。
Station Document: 车站文件:
{
"_id": "588a777d4e26720e7afa7e1e",
"phone": "(007) – 007 – 7007",
"name": "name1",
"email": "name1@email.com",
"reports": [
{
"status": "Submitted",
"date": "2014-01-31T01:48:57.487Z",
"_id": "588fed278b50cd180bd6cc15"
}
]
}
Report Document 报告文件
{
"_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 Call 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);
})
});
})
You are doing mistake while updating the station
object. 更新
station
对象时出错。 Use findOneAndUpdate
to find the matching Station
document, and then change the status of the matched reports item(matched using reports._id). 使用
findOneAndUpdate
查找匹配的Station
文档,然后更改匹配的报告项目(使用reports._id进行匹配)的状态。
Try this: 尝试这个:
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
will find the array element whose _id
is req.params.id
and report.$.status
will update only the matching element of the array. report._id
将找到_id
为req.params.id
的数组元素, report.$.status
将仅更新数组的匹配元素。
For more information on positional $(update) operator
, Read mongoDB positional Documentation . 有关
positional $(update) operator
更多信息,请阅读mongoDB位置文档 。
Also, i would suggest to save
the report
object in the callback of update
. 另外,我建议
save
report
对象save
在callback of update
的callback of update
。 As nodejs
is asynchronous
, it will not wait for the update
to finish, if you are saving report
outside of the callback. 由于
nodejs
是asynchronous
,因此,如果您将report
保存在回调之外,它将不等待update
完成。 And, you might get Cant set the headers after they are sent error
. 而且,你可能会得到广东话设置的标头发送之后
error
。 Thus, its recommended to do it in the callback. 因此,建议在回调中执行此操作。
Thus your final API code would look like: 因此,您最终的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 Alternate Method UPDATE 备用方法
Another way can be, You can proceed in the original way, but don't save the data inside the forEach, instead save the data sheet forEach finishes. 另一种方法是,您可以按原始方式进行操作,但不要将数据保存在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);
});
})
})
Hope this helps! 希望这可以帮助!
After multiple attempts, and with the help of Ravi, I was able to figure out a solution that worked for me pretty well. 经过多次尝试,并在Ravi的帮助下,我找到了一个对我来说非常有效的解决方案。 The only thing that changed was my
API
call. 唯一改变的是我的
API
调用。 The rest of the code was unchanged. 其余代码未更改。
Hope this helps someone having similar needs. 希望这可以帮助有类似需求的人。
API CALL 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});
});
})
});
})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.