我有一个Express / Mongo后端,正在尝试“手动”更新数据。
我打电话给UserObj.findById(req.params.id, function(err,doc){... callback ...})
在回调函数中,我更新了文档。我可以将push
的新数据放入doc
的查询结果中(然后再输入到Mongo DB中),但是如果我尝试更新doc
中的现有数据,虽然它会显示在我的console.log
doc
已经更新,当我查看Mongo数据库时,数据实际上尚未更新。
这是Mongo的默认行为,还是我在某个地方犯了错误?如果这是默认行为,那么最佳的解决方法是什么?我试图避免使用内置的findByIdAndUpdate
函数,因为我希望对如何处理每个字段有更多的手动控制。 (例如,对于某些字段我想push
新数据,而其他字段我想update
现有数据。)
以下是控制器回调(users_controller.user_details_update
)的相关部分:
exports.user_details_post = [(req, res, next)=> {
//LOG, VALIDATE, SANITIZE
. . .
. . .
//SAVE
(req,res, next) =>{
const errors = validationResult(req);
if (!errors.isEmpty()) {
// Handle Validation Errors
} else {
let user = UserObj.findById(req.params.id, function(err,doc){
let activeArr = [];
let maxActive = 0;
if (err) {}
Object.keys(doc["_doc"]).forEach(sec=>{
Object.keys(doc["_doc"][sec]["_doc"]).filter(fld=>doc["_doc"][sec]["_doc"][fld].hasOwnProperty("value")).forEach(fld=> {
activeArr = [];
maxActive = +doc["_doc"][sec]["_doc"][fld]["attr"]["active"].reduce((acc,cur)=>Math.max(acc, cur),-Infinity);
Object.keys(req.body).filter(reqFld=>
new RegExp(`^${fld}__${sec}--[0-9]*-[0-9]*`).test(reqFld)).forEach(reqFld=> {
let activeVal = +reqFld.split(SEC_SPLIT_CHAR)[1].split(ROW_SPLIT_CHAR)[1];
if (activeVal > maxActive) {
doc["_doc"][sec]["_doc"][fld]["value"].push(req.body[reqFld]) // THIS
// WORKS FINE
} else if (activeVal===maxActive) {
doc["_doc"][sec]["_doc"][fld]["value"][0]=req.body[reqFld] // NO ERRORS
// THROWN, BUT THE
// DOCUMENT DOESN'T GET
// UPDATED IN MONGODB
. . .
. . .
// SAVE
doc.save(function(err){ // SAVE WORKS OK. NO ERRORS
if (err) { return next(err);}
});
console.log("redirecting . . . ")
res.redirect("http://localhost:4200/"); // EXITS NORMALLY
});
}
},
];
此外,当我检查回调中的doc
对象时,我发现它在对象层次结构的前两个级别中包含一些“添加的”字段["_doc"]
。我的问题与我如何处理这些“额外”字段有关吗?还是我不得不创建一个全新的用户对象,将更新的数据写入该对象,然后从旧对象复制_id
? (这样做似乎有点浪费)。
谢谢!
==========
除了将已更新的doc
复制到新的UserObj
,删除旧的UserObj
,然后切换{{1 }},将新用户迁移到旧用户的_id
上,如下所示:
_id
就个人而言,虽然可行,但我发现此解决方案有些笨拙,有些不太雅致。如果有人能找到更好的解决方案,我将不胜感激,并将选择它作为答案。谢谢!