MongoDB仅更新对象中已更改的字段,而不是替换整个对象

时间:2019-01-08 07:31:34

标签: node.js mongodb

我要更新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不要替换整个对象,而只是更新提到的那些键?

2 个答案:

答案 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}, )