【问题标题】:Remove sub-document from Mongo with mongoose使用 mongoose 从 Mongodb 中删除子文档
【发布时间】: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 这个词。你能提供一个堆栈跟踪吗?

标签: node.js mongoose


【解决方案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 }
    

    【讨论】:

      猜你喜欢
      • 2017-09-28
      • 2019-01-04
      • 2011-05-28
      • 1970-01-01
      • 2023-03-28
      • 2019-05-27
      • 1970-01-01
      相关资源
      最近更新 更多