node.js - 匹配主文档和嵌套对象的 id 后更新嵌套对象
问题描述
我有以下结构的 mongo 文档
{
"registrationDate": "2020-06-09T18:15:00.000Z",
"_id": "5ee6dd003a97c93c6436349c",
"ofSite": "5ee19fe085d70733243c3309",
"patientID": "NGH-123",
"neocareID": "",
"babyName": "Joey",
"motherName": "Phoebe",
"dateOfBirth": "2020-06-08T18:15:00.000Z",
"babySex": "Female",
"birthType": "Single",
"patientType": "Referred",
"mobileNumber": "9802824412",
"mobileOf": "Family Member",
"linkedFCHV": "Racheal",
"FCHVmobile": "9876225420",
"address": "Holloywood",
"examinations": [
{
"ODExam": {
"plusODExam": "No",
"zoneODExam": "I",
"ropODExam": "No",
"ropODStage": 1,
"categoryOD": "None",
"apROPOD": "Yes"
},
"OSExam": {
"plusOSExam": "No",
"zoneOSExam": "I",
"ropOSExam": "Yes",
"ropOSStage": 1,
"categoryOS": "None",
"apROPOS": "Yes"
},
"FindingFollowUp": {
"ropFindings": "All Good so far",
"followUpPlan": "Follow up in next month",
"nameOfExaminer": "Luzan",
"followUpDate": "2020-07-07T18:15:00.000Z"
},
"_id": "5ee6dd793a97c93c6436349e",
"examinationDate": "06/12/2020",
"currentPMA": 5,
"daysOfLife": 42,
"currentWeight": 4500,
"visitType": "First"
},
{
"ODExam": {
"plusODExam": "No",
"zoneODExam": "I",
"ropODExam": "No",
"ropODStage": 1,
"categoryOD": "None",
"apROPOD": "Yes"
},
"OSExam": {
"plusOSExam": "No",
"zoneOSExam": "I",
"ropOSExam": "Yes",
"ropOSStage": 1,
"categoryOS": "None",
"apROPOS": "Yes"
},
"FindingFollowUp": {
"ropFindings": "All Good so far",
"followUpPlan": "Follow up in next month",
"nameOfExaminer": "Luzan",
"followUpDate": "2020-07-07T18:15:00.000Z"
},
"_id": "5ee6dd913a97c93c643634a0",
"examinationDate": "06/12/2020",
"currentPMA": 5,
"currentWeight": 4500,
"visitType": "First"
},
{
"ODExam": {
"plusODExam": "No",
"zoneODExam": "I",
"ropODExam": "No",
"ropODStage": 1,
"categoryOD": "None",
"apROPOD": "Yes"
},
"OSExam": {
"plusOSExam": "No",
"zoneOSExam": "I",
"ropOSExam": "Yes",
"ropOSStage": 1,
"categoryOS": "None",
"apROPOS": "Yes"
},
"FindingFollowUp": {
"ropFindings": "All Good so far",
"followUpPlan": "Follow up in next month",
"nameOfExaminer": "Luzan",
"followUpDate": "2020-07-07T18:15:00.000Z"
},
"_id": "5ee6ddf13a97c93c643634a2",
"examinationDate": "06/12/2020",
"currentPMA": 5,
"currentWeight": 4500,
"visitType": "First"
},
{
"ODExam": {
"plusODExam": "No",
"zoneODExam": "I",
"ropODExam": "No",
"ropODStage": 1,
"categoryOD": "None",
"apROPOD": "Yes"
},
"OSExam": {
"plusOSExam": "No",
"zoneOSExam": "I",
"ropOSExam": "Yes",
"ropOSStage": 1,
"categoryOS": "None",
"apROPOS": "Yes"
},
"FindingFollowUp": {
"ropFindings": "All Good so far",
"followUpPlan": "Follow up in next month",
"nameOfExaminer": "Luzan",
"followUpDate": "2020-07-07T18:15:00.000Z"
},
"_id": "5ee6de093a97c93c643634a4",
"examinationDate": "06/12/2020",
"currentPMA": 5,
"currentWeight": 4500,
"visitType": "First"
}
],
"__v": 4
}
让我告诉你我想在这里做什么。这是我的路线
adminRoutes.post(
'/examination/:patientID/:examID',
userController.ensureAuthenticated,
examController.findOneAndUpdate
)
我将_id
患者作为:patientID
(文档)和_id
嵌套检查对象作为传递:examID
,我的目标是通过匹配检查 ID 来更新患者的检查。这是我的控制器。
/**
* POST /admin/examination/:patientID/:examID
**/
exports.findOneAndUpdate = function (req, res) {
const query = { examinations: { $elemMatch: { _id: new ObjectId(req.params.examID) } } }
const update = {
$set: {
examinationDate: req.body.examinationDate,
daysOfLife: req.body.daysOfLife,
currentPMA: req.body.currentPMA,
currentWeight: req.body.currentWeight,
visitType: req.body.visitType,
ODExam: {
plusODExam: req.body.plusODExam,
zoneODExam: req.body.zoneODExam,
ropODExam: req.body.ropODExam,
ropODStage: req.body.ropODStage,
categoryOD: req.body.categoryOD,
apROPOD: req.body.apROPOD
},
OSExam: {
plusOSExam: req.body.ropOSExam,
zoneOSExam: req.body.zoneOSExam,
ropOSExam: req.body.ropOSExam,
ropOSStage: req.body.ropOSStage,
categoryOS: req.body.categoryOS,
apROPOS: req.body.apROPOS
},
FindingFollowUp: {
ropFindings: req.body.ropFindings,
followUpPlan: req.body.followUpPlan,
nameOfExaminer: req.body.nameOfExaminer,
followUpDate: req.body.followUpDate
}
}
}
const options = { arrayFilters: [{ 'examinations._id': new ObjectId(req.params.examID) }] }
Patient.updateOne(query, update, options, function (err, result) {
if (err) {
console.log(err)
res.send(err)
} else {
console.log(result)
res.send(result)
}
})
}
我参考了Selecting and update a nested object by it's ObjectId in Mongoose.js。但我收到一个错误。
MongoError: The array filter for identifier 'examinations' was not used in the update { $set: { daysOfLife: 45 } }
我在做吗?在这种情况下,什么可能是更新单个检查的有效方法。这是仅更新已更改数据的正确方法吗?感谢您花时间阅读本文。
更新[已解决]。我在@thammada.ts 的评论的帮助下修复了它。都是他的功劳。将我的更新更改为:
const update = {
$set: {
'examinations.$[exam].examinationDate': req.body.examinationDate,
'examinations.$[exam].daysOfLife': req.body.daysOfLife,
'examinations.$[exam].currentPMA': req.body.currentPMA,
'examinations.$[exam].currentWeight': req.body.currentWeight,
'examinations.$[exam].visitType': req.body.visitType,
'examinations.$[exam].ODExam': {
plusODExam: req.body.plusODExam,
zoneODExam: req.body.zoneODExam,
ropODExam: req.body.ropODExam,
ropODStage: req.body.ropODStage,
categoryOD: req.body.categoryOD,
apROPOD: req.body.apROPOD
},
'examinations.$[exam].OSExam': {
plusOSExam: req.body.ropOSExam,
zoneOSExam: req.body.zoneOSExam,
ropOSExam: req.body.ropOSExam,
ropOSStage: req.body.ropOSStage,
categoryOS: req.body.categoryOS,
apROPOS: req.body.apROPOS
},
'examinations.$[exam].FindingFollowUp': {
ropFindings: req.body.ropFindings,
followUpPlan: req.body.followUpPlan,
nameOfExaminer: req.body.nameOfExaminer,
followUpDate: req.body.followUpDate
}
}
}
并用于'exam.id'
arrayFilters。
解决方案
你必须改变你的update
和options
如下
/*
Keep in mind that this will replace the whole element,
if you have other fields not included in the update, they will be removed.
To update new fields without replacing the element,
you have to specify all the fields like this
{
$set: {
...
"examinations.$[exam].examinationDate": req.body.examinationDate,
"examinations.$[exam].daysOfLife": req.body.daysOfLife,
...
"examinations.$[exam].ODExam.plusODExam": req.body.plusODExam,
"examinations.$[exam].ODExam.zoneODExam": req.body.zoneODExam
...
}
}
*/
const update = {
$set: {
"examinations.$[exam]": {
_id: new ObjectId(req.params.examID),
examinationDate: req.body.examinationDate,
daysOfLife: req.body.daysOfLife,
currentPMA: req.body.currentPMA,
currentWeight: req.body.currentWeight,
visitType: req.body.visitType,
ODExam: {
plusODExam: req.body.plusODExam,
zoneODExam: req.body.zoneODExam,
ropODExam: req.body.ropODExam,
ropODStage: req.body.ropODStage,
categoryOD: req.body.categoryOD,
apROPOD: req.body.apROPOD
},
OSExam: {
plusOSExam: req.body.ropOSExam,
zoneOSExam: req.body.zoneOSExam,
ropOSExam: req.body.ropOSExam,
ropOSStage: req.body.ropOSStage,
categoryOS: req.body.categoryOS,
apROPOS: req.body.apROPOS
},
FindingFollowUp: {
ropFindings: req.body.ropFindings,
followUpPlan: req.body.followUpPlan,
nameOfExaminer: req.body.nameOfExaminer,
followUpDate: req.body.followUpDate
}
}
}
}
const options = {
arrayFilters: [{ 'exam._id': new ObjectId(req.params.examID) }]
}
提示:您实际上不必$elemMatch
在查询中执行此操作。你可以做
const query = { "examinations._id": new ObjectId(req.params.examID) }
或者确保它正在更新正确的患者
const query = {
"_id": new ObjectId(req.params.patientID),
"examinations._id": new ObjectId(req.params.examID)
}
推荐阅读
- javascript - 如何在不创建新的单独文件的情况下在页面链接上添加密码保护?
- random - 当碰撞可能且昂贵时,如何生成不重复的随机值?
- swift - 打开 UIPickerView 时出现的项目不被视为“已选择”
- rest - 在设计 REST API 时,是否可以要求在允许创建资源之前完成对资源的搜索?
- texmacs - TeXmacs 条件独立符号
- rust - 如何迭代使用 RwLock 构建的并发哈希映射的可变值?
- firebase - 如何使用 Flutter 更新云 Firestore 上文档的字段?
- c++ - Visual Studio 不运行我的代码,而其他 IDE 运行
- javascript - 无法将状态从父组件传递给子组件(番茄钟状态计数器)
- scala - Spark 2.0 - 将数据帧拆分为子数据帧而不使用 createOrReplaceTempView