使用Mongoose从MongoDB文档中删除密钥


103

我正在使用Mongoose库通过node.js访问MongoDB

有没有办法从文档中删除密钥?即不只是将值设置为null,而是将其删除?

User.findOne({}, function(err, user){
  //correctly sets the key to null... but it's still present in the document
  user.key_to_delete = null;

  // doesn't seem to have any effect
  delete user.key_to_delete;

  user.save();
});

1
我以为自己找到了,但是经过一些测试:可能没有。但是,在该主题上有一些很好的讨论。groups.google.com/group/mongoose-orm/browse_thread/thread/…–
史蒂芬·史蒂芬(Stephen)

大声笑没关系,我想这是您的帖子!
斯蒂芬,

Answers:


168

在早期版本中,您需要删除node-mongodb-native驱动程序。每个模型都有一个收集对象,该对象包含node-mongodb-native提供的所有方法。因此,您可以执行以下操作:

User.collection.update({_id: user._id}, {$unset: {field: 1 }});

从2.0版开始,您可以执行以下操作:

User.update({_id: user._id}, {$unset: {field: 1 }}, callback);

从2.4版开始,如果已经有模型实例,则可以执行以下操作:

doc.field = undefined;
doc.save(callback);

此问题已在Mongoose 2.X中修复,因此您可以忽略该集合。
staackuser2 2011年

4
无论使用User.update({ _id: id }, { $unset: { field: 1 }}, callback)还是如果您有文档实例,请将路径设置为undefined然后保存:doc.field = undefined; doc.save()
aaronheckmann 2012年

25
请注意,如果您要删除模式中不再定义的旧属性,则需要执行doc.set('field', undefined)
evilcelery 2013年

3
那删除doc.field.foo呢?
chovy

28
@evilcelery doc.set('field', undefined)可能还不够,因为严格模式(默认)不允许设置模式中不再存在的字段。doc.set('field', undefined, { strict: false })工作正常。
Alexander Link


30

我使用猫鼬,并使用上述任何功能满足了我的要求。该函数编译没有错误,但该字段仍将保留。

user.set('key_to_delete', undefined, {strict: false} );

为我做了把戏。


Upvoting这个有用的答案,太糟糕了@亚历山大环节没能在2015年(应答返回stackoverflow.com/questions/4486926/...
w00t

1
感谢您的回答,对我来说,其他解决方案不适用于嵌套在数组中的对象!
BenSower

@BenSower这也是我的情况。仅此解决方案有效,因为找到特定文档的ID后必须删除带有数组的字段
Luis Febro

请注意,字符串是键的路径。因此,如果要删除的对象是嵌套的,则必须指向它的路径。这个答案解决了我的问题!
Bradyo,

8

使用mongo语法删除某些键时,需要执行以下操作:

{ $unset : { field : 1} }

似乎在猫鼬一样。

编辑

检查这个例子。


您能否弄清楚这个答案,并给出与上述示例代码相关的代码示例?
Daniel Beardsley

对不起,但是我没有猫鼬的经验。上面的语法是mongo语法,所以我想任何语言的驱动程序都支持。我找到了一些示例,请在我的答案中进行检查。
Andrew Orsich 2011年

1

这可能是像使用这样的附带问题吗

function (user)

代替

function(err, user)

用于查找的回调?正如我已经遇到的情况那样,只是尝试帮助解决这个问题。


1

猫鼬文档不是普通的javascript对象,这就是为什么您不能使用delete运算符的原因。(或unset来自“ lodash”库)。

您的选择是设置doc.path = null || undefined或使用Document.toObject()方法将猫鼬doc转换为纯对象,然后从那里像往常一样使用它。在mongoose api-ref中阅读更多信息:http : //mongoosejs.com/docs/api.html#document_Document-toObject

示例如下所示:

User.findById(id, function(err, user) {
    if (err) return next(err);
    let userObject = user.toObject();
    // userObject is plain object
});

1

尝试:

User.findOne({}, function(err, user){
  // user.key_to_delete = null; X
  `user.key_to_delete = undefined;`

  delete user.key_to_delete;

  user.save();
});

0

所有这些答案的问题在于它们只能用于一个领域。例如,假设我要从我的文档中删除所有字段,如果它们是空字符串""。首先,您应该检查field是否为空字符串,并将其放入$unset

function unsetEmptyFields(updateData) {
  const $unset = {};
  Object.keys(updatedData).forEach((key) => {
    if (!updatedData[key]) {
      $unset[key] = 1;
      delete updatedData[key];
    }
  });
  updatedData.$unset = $unset;

  if (isEmpty(updatedData.$unset)) { delete updatedData.$unset; }

  return updatedData;
}

function updateUserModel(data){
const updatedData = UnsetEmptyFiled(data);

    const Id = "";
    User.findOneAndUpdate(
      { _id: Id },
      updatedData, { new: true },
    );
}

0

如果要从集合中删除密钥,请尝试此方法。这对我有用

 db.getCollection('myDatabaseTestCollectionName').update({"FieldToDelete": {$exists: true}}, {$unset:{"FieldToDelete":1}}, false, true);

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.