У меня есть бэкэнд Express / Mongo, и я пытаюсь обновить данные «вручную».
Я звоню UserObj.findById(req.params.id, function(err,doc){... callback ...})
И в функции обратного вызова я обновляю документ. Я могу push
новые данные в результате запроса doc
(а затем в базу данных Mongo), но если я попытаюсь обновить существующие данные в doc
, в то время как в моем console.log
это показывает, doc
был обновлен, когда я смотрю в Mongo DB, данные фактически не обновлялись.
Это поведение по умолчанию в 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
, а затем переключите _id
нового пользователя на _id
старого пользователя, как показано ниже:
. . .
. . .
thisUser = doc;
});
user.remove().then(result=>{
sameUser = new UserObj(thisUser);
sameUser._id = thisUser._id;
},err=>next(err)).then(result=>{
sameUser.save(err=>{
console.log("Saving DETAILS . . . ")
if (err) { return next(err);}
console.log("Saved DETAILS . . . Now redirecting ");
res.redirect("http://localhost:4200/");
})
})
Лично, пока онработает, я нахожу это решение слегка грязным и несколько не элегантным. Если кто-нибудь сможет найти лучшее решение, я буду очень признателен и выберу это в качестве ответа. Спасибо!