使用 mongoose 从 Mongodb 中删除子文档

Posted

技术标签:

【中文标题】使用 mongoose 从 Mongodb 中删除子文档【英文标题】:Remove sub-document from Mongo with mongoose 【发布时间】:2013-09-04 10:12:12 【问题描述】:

我正在尝试从存储在 mongoose 文档中的集合中删除一个项目。我的文档如下所示:


  "__v": 3,
  "_id": "5221040475f174d59a000005",
  "items": [
    
      "sku": 1321654654613213,
      "name": "goldfish",
      "quantity": 12,
      "_id": "52224ed5bd9d340000000003"
    ,
    
      "sku": 12,
      "name": "goldfish",
      "quantity": 13,
      "_id": "52225dcbf2f1e40000000003"
    ,
    
      "sku": 1299,
      "name": "goldfish",
      "quantity": 13,
      "_id": "522260b6f2f1e40000000004"
    
  ]

我想删除sku为12的金鱼。我正在执行以下操作:

var inventory = res.locals.content;
inventory.items.remove( sku: req.params.itemSku, function (err, item) 
  if (err) 
    console.log('error occurred', err);
    res.send('error');
  
  else 
    res.send('Item found and deleted');
    return; 
  
);

当我这样做时,我收到错误“TypeError: Cannot read property 'equals' of undefined”。我不明白为什么。

【问题讨论】:

您提供的代码中没有出现 equals 这个词。你能提供一个堆栈跟踪吗? 【参考方案1】:

子文档现在有一个remove 函数。从规范中使用如下:

var doc = parent.children.id(id).remove();
parent.save(function (err) 
  if (err) return handleError(err);
  console.log('the sub-doc was removed')
);

【讨论】:

这是原子调用吗? 实际上,实际保存是原子的,我查看了源代码,它看起来像 remove() 使用 MongooseArray.pull,根据 v4 文档:Pulls items from the array atomically. - 如果您担心数组索引不同步。话虽如此,您也可以使用MongooseArray.pull 来做同样的事情,就像接受的答案所述。 @OllyBarca 我确实做到了,因此“使用如下规范”。【参考方案2】:

您需要inventory.items.pull(req.params.itemSku),然后是inventory.save 呼叫。 .remove 用于***文档

【讨论】:

我在使用inventory.items.pull(sku: req.params.itemSku); 时没有收到任何错误,但这会返回整个数组而不是具有匹配 sku 的元素。这是为什么呢? pull 返回this,可能是为了可链接性,所以你可以这样做inventory.items.pull(blah).push(blah)。 github.com/LearnBoost/mongoose/blob/…【参考方案3】:

从数组中删除子文档

我发现从 array 中查找和删除子文档的最好和最完整的解决方案是使用 Mongoose 的 $pull 方法:

Collection.findOneAndUpdate(
     _id: yourCollectionId ,
     $pull:  subdocumentsArray:  _id: subdocumentId  ,
     new: true ,
    function(err) 
        if (err)  console.log(err) 
    
)

new: true 确保返回数据的更新版本,而不是旧数据。

【讨论】:

new: true 不确保现有文档被覆盖。它只返回更新数据的结果,而不是数据库中的旧数据。所以它的结果是子文档被删除。【参考方案4】:

最后!

MongoDB:

"imgs" : "other" : [ 
        "crop" : "../uploads/584251f58148e3150fa5c1a7/photo_2016-11-09_21-38-55.jpg",
        "origin" : "../uploads/584251f58148e3150fa5c1a7/o-photo_2016-11-09_21-38-55.jpg",
        "_id" : ObjectId("58433bdcf75adf27cb1e8608")
                                    
                            ]
                    ,
router.get('/obj/:id',  function(req, res) 
var id = req.params.id;



Model.findOne('imgs.other._id': id, function (err, result) 
        result.imgs.other.id(id).remove();
        result.save();            
    );

【讨论】:

【参考方案5】:

您可以简单地使用$pull 删除子文档。

    Collection.update(
    _id: parentDocumentId
  , 
    $pull: 
      subDocument: 
        _id: SubDocumentId
      
    
  );

这将根据给定 ID 找到您的父文档,然后从子文档中删除与给定条件匹配的元素。

【讨论】:

但为此我需要知道不需要的父 ID 和子文档 ID。【参考方案6】:
    const deleteitem = (req, res) => 
    var id = req.body.id
    var iditem = req.body.iditem

    Venta.findOne('_id': id, function(err,result)
        if (err) 
            console.log(err);            
        else
            result.items.pull(iditem)
            result.save()
        
    )
module.exports = deleteitem 

【讨论】:

以上是关于使用 mongoose 从 Mongodb 中删除子文档的主要内容,如果未能解决你的问题,请参考以下文章

使用 mongoose 从 Mongodb 中删除子文档

从 Mongoose/MongoDB 中的数组中删除对象

NodeJs MongoDb Mongoose - 如何从多维数组中删除项目?

mongoose:使用$ pull删除嵌入式文档数组中的值(MongoDB 3.4版本)

如何在 Mongoose(MongoDB 包装器)中删除一行 [重复]

如何将 MongoDB 查询从 Node.js 驱动程序格式调整为 Mongoose 格式