我要更新MongoDB中包含对象的文档。 由于更新后的对象是由用户提供的,因此我不知道他将要更改什么。
例如,我在用户集合中有此文档:
RETURN
用户可以编辑名字和姓氏,但不能编辑电话。
这是{
_id: 1,
date: new Date(),
info: {
first_name: "a",
last_name: "b",
phone: "c"
}
}
(我从用户那里收到的输入):
req.body
现在,为了仅更新“ info.first_name”并保留信息对象中存储的其他字段,我必须设置一个更新查询,如下所示:
{
info: {
first_name: "aa"
}
}
但是输入可以是动态和可变的。 我不知道它是否总是被更新的名字,可以是姓氏,甚至是地址等其他子对象:“ info.address.city”(例如)
因此,我会像这样处理这些更新:
db.users.update({}, {$set: {"info.first_name": req.body.info.first_name}}, cb);
就是这样。它有效,但是我对此有疑问。 它取代了整个信息对象,并且不保留存储在其中的其他键-手机将被删除,姓氏将被删除。
是否有一种方法可以告诉MongoDB不要替换整个对象,而只是更新提到的那些键?
答案 0 :(得分:0)
我也调查了它,您不能将mongo设置为仅更新特定字段。相反,您可以做的是根据输入来动态构建查询。
我通常会遍历输入,然后验证允许修改的内容,并基于该内容构建动态查询:
var updateQuery = {};
for(key of req.body.info) {
if (req.body.info.hasOwnProperty(key) && canBeModified(key)) //this would be a function to validate what can be updated
updateQuery['info.' + key] = req.body.info[key]};
}
db.users.update({}, {$set: updateQuery}, cb);
答案 1 :(得分:0)
在数据库中读取当前条目并将req.body散布在当前条目上会更容易吗?
// read current entry in database
let currentObject = await user.findOne({_id});
// merge current entry with changed updated key:values
let newObject = ( currentObject, ...req.body );
// write update to database
let user.findOneAndUpdate({_id}, {$set: newObject}, )