如何仅更新MongoDB数据库中对象的某些属性

Jes*_*son 2 javascript mongoose node.js express ecmascript-6

我下面的代码不允许API用户通过传递一个请求属性来仅更新一个字段。我可以在处删除null userObj,但是UI开发人员将必须从数据库传递现有数据来进行更新,这不是最佳实践。

这是我的Express路线:

router.put('/user', (req, res) => {
  const userObj = {
    name: req.body.name || null,
    location: {
      city: req.body.city || null
      },
      phone: req.body.phone || null
    };

  User.updateUser(req.body.id, userObj)
});
Run Code Online (Sandbox Code Playgroud)

这是我的猫鼬模型的updateUser功能:

module.exports.updateUser = (_id, userObj, callback) => {
  User.findOneAndUpdate({_id}, userObj, { upsert: true, 'new': true }, callback);
}
Run Code Online (Sandbox Code Playgroud)

Li3*_*357 6

首先,要解决仅更新某些特定属性的问题,您必须使用$set运算符仅设置特定字段。当userObj直接传递给findOneAndUpdate您时,将重置整个对象,因此必须传递所有现有属性。用途$set

User.findOneAndUpdate({_id}, { $set: userObj }, { upsert: true, new: true }, callback);
Run Code Online (Sandbox Code Playgroud)

这将仅将中定义的属性更新userObj为其新值,并且不影响其他任何内容。另外,您可以只findByIdAndUpdate在这种用例中使用:

User.findByIdAndUpdate(_id, { $set: userObj }, { upsert: true, new: true }, callback);
Run Code Online (Sandbox Code Playgroud)

接下来,您不应该使用PUT。使用补丁。PUT意味着将资源放在某个URL上,如果资源已经存在,则将其完全替换。PATCH意味着您仅更新资源的一些属性,并且确实替换了整个属性。这不会影响应用程序的功能,但这是一个巨大的语义问题和最终用户问题,因为他们期望PATCH。

  • @JessieAnderson有。如果只想“仅”更新一个或多个特定属性,则无论使用“ findByIdAndUpdate”还是“ findOneAndUpdate”,始终使用“ $ set”。 (2认同)
  • @JessieAnderson 如果您不想更新 `name`,请不要传递 `name`。只传入你想覆盖的属性:`{ age: 10 }`。 (2认同)