Javascript MongoDB-Mongoose:如何使用Mongoose同时更新两个独立的嵌入式文档?

Javascript MongoDB-Mongoose:如何使用Mongoose同时更新两个独立的嵌入式文档?,javascript,node.js,mongodb,api,mongoose,Javascript,Node.js,Mongodb,Api,Mongoose,因此,我试图在一次API调用中更新myReport文档和myStation.reports子文档中的字段status,它是一个对象数组。问题是,在进行API调用时,我能够更新报告文档,但不能更新station文档。调用后,console.log(station.reports)返回预期的子文档,该子文档是:[{{U id:“588fed278b50cd180bd6cc15”,“日期”:“2017-01-31T01:48:57.487Z”,“状态”:“存档”}],但它不会保存在my DB中的相应站

因此,我试图在一次API调用中更新my
Report
文档和my
Station.reports
子文档中的字段
status
,它是一个对象数组。问题是,在进行API调用时,我能够更新报告文档,但不能更新station文档。调用后,
console.log(station.reports)
返回预期的子文档,该子文档是:
[{{U id:“588fed278b50cd180bd6cc15”,“日期”:“2017-01-31T01:48:57.487Z”,“状态”:“存档”}]
,但它不会保存在my DB中的相应站点文档中。求求你,我需要帮助。谢谢

电台文件:

{
    "_id": "588a777d4e26720e7afa7e1e",
    "phone": "(007) – 007 – 7007",
    "name": "name1",
    "email": "name1@email.com",
    "reports": [
      {
        "status": "Submitted",
        "date": "2014-01-31T01:48:57.487Z",
        "_id": "588fed278b50cd180bd6cc15"
      }
    ]
}  
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});
            });
        })
    });
})
报告文档

{
    "_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"
}  
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);
        })
    });
})
API调用

{
    "_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"
}  
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);
        })
    });
})

更新
站点
对象时出错。使用
findOneAndUpdate
查找匹配的
站点
文档,然后更改匹配报告项的状态(使用报告进行匹配。\u 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.\u id
将查找其
\u id
req.params.id
report的数组元素。$。status
将仅更新数组的匹配元素

有关
位置$(更新)运算符的详细信息,请阅读

另外,我建议在更新的
回调中
保存
报告
对象。由于
nodejs
asynchronous
,如果您在回调之外保存
报告
,它将不会等待
更新
完成。而且,您可能会收到发送后无法设置标题的消息
错误
。因此,建议在回调中执行此操作

因此,您的最终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中,而是保存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);
        });
    })
})

希望这有帮助

在多次尝试之后,在拉维的帮助下,我找到了一个对我非常有效的解决方案。唯一改变的是我的
API
调用。代码的其余部分保持不变。
希望这能帮助有类似需求的人

API调用

{
    "_id": "588a777d4e26720e7afa7e1e",
    "phone": "(007) – 007 – 7007",
    "name": "name1",
    "email": "name1@email.com",
    "reports": [
      {
        "status": "Submitted",
        "date": "2014-01-31T01:48:57.487Z",
        "_id": "588fed278b50cd180bd6cc15"
      }
    ]
}  
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});
            });
        })
    });
})

嗨,拉维。谢谢你的回复。我想尝试一下您的建议,但是首先考虑到子文档
reports
是一个数组,您如何可能编写
报告。这可能会破坏整个局面,对吗?可能我遗漏了什么不不,你可以像那样在数组中查询,然后
报告。$.status
将真正只更新报告数组中匹配的元素。我不知道这个技巧。好啊让我现在就试试。试过了,但没用。仍然会更新
报告
对象,但不会更新
站点.报告
子文档。我甚至尝试了
$push
而不是
$set
没有luckCan可以检查是否有错误,但我认为我编辑的答案应该有效。