节点/猫鼬 - 从数组中删除 ObjectId [重复]

Posted

技术标签:

【中文标题】节点/猫鼬 - 从数组中删除 ObjectId [重复]【英文标题】:Node/Mongoose - remove ObjectId from Array [duplicate] 【发布时间】:2018-11-19 10:13:26 【问题描述】:

我正在构建的网站上有一个具有 cmets 功能的页面。该网站就像露营地的 Yelp,mongo db 中集合中的每个露营地都有一个字段 - cmets - 存储在该露营地上发布的每条评论的 id,并且 id 指的是另一个名为 cmets 的集合中的对象。添加、编辑、查看和删除 cmets 都有效,除了删除评论时,该评论的 id 不会从其关联露营地的 cmets 数组中删除。

这是目前一个露营地的记录示例:

 
     "_id" : ObjectId("5b18331953b9811c54ddc4cd"),
          "contact" :  
          "phone" : "403-748-4066", 
          "email" : "", 
          "website" : "https://www.albertaparks.ca/parks/central/aspen-beach-pp/information-facilities/camping/lakeview/" 
     , 
     "author" :  
          "id" : ObjectId("5a998953342cbc7fe8521ef5"), 
          "username" : "Adam" 
     , 
     "createdAt" : ISODate("2018-06-06T19:04:25.418Z"), 
     "comments" : [ 
          ObjectId("5b1bf59f8f21e152cce41b49") 
     ], 
     "name" : "Lakeview", 
     "cost" : "40", 
     "location" : "Range Rd 284, Bentley, AB T0C 0J0, Canada", 
     "image" : "https://c1.staticflickr.com/9/8620/16612167676_6418f1b470_b.jpg",
      "description" : "Open, pull-through sites are well-suited to RVs. There are unserviced, power, and power/water options. Trees provide some shade from the summer sun. There are many amenities available including a boat launch, playground, sewage disposal, flush toilets and showers. Camp along Gull Lake and enjoy swimming, boating, and the beach. Explore the trails and boardwalks for walking, biking, bird and wildlife watching. ", 
     "lat" : 52.4357744, 
     "__v" : 1, 
     "long" : -113.9873582 

正如您所见,campsite 对象当前引用了一条评论,但如果我要通过 UI 删除评论,它将停止显示评论,因为它将从 cmets 集合中删除,但对评论的引用露营地对象将保留。这是我目前删除评论的代码:

app.delete("/campgrounds/:id/comments/:comment_id", middleware.checkCommentOwnership, function(req, res)
    // RESTful - DESTROY
    Comment.findByIdAndRemove(req.params.comment_id, function(err)
        if(err)
            req.flash("error", "Uh Oh! Something went wrong.");
            res.redirect("/campgrounds");
        
        Campground.findById(req.params.id, function(err, campground)
            if(err)
                req.flash("error", "Uh Oh! Something went wrong.");
                res.redirect("/campgrounds");
            
            campground.comments.remove(req.params.comment_id);
            req.flash("success", "Comment has been deleted!");
            res.redirect("back");
        );
    );
);

然而行

campground.comments.remove(req.params.comment_id); 

似乎不起作用。我也(粗略地)尝试过

campground.comments.remove("ObjectId(\"" + req.params.comment_id + "\")")

尝试在 cmets 数组中镜像存储 id 的格式,但这会引发此错误:

CastError: Cast to ObjectId failed for value "ObjectId("5b1bf4215f319752ab28ba49")" at path "comments"

我主要使用 Mongoose 与数据库交互。

对不起,如果这是冗长的或重复的,我试图研究解决方案,但什么也没找到 - 至少没有什么我能理解的!

谢谢。

【问题讨论】:

【参考方案1】:

您需要使用 mongodb $pull 运算符才能从数组中删除 comment_id...

Campground.update( _id: req.params.id ,  $pull:  comments: req.params.comment_id  , function(err, campground)
    if(err)
        req.flash("error", "Uh Oh! Something went wrong.");
        return res.redirect("/campgrounds");
    
    req.flash("success", "Comment has been deleted!");
    return res.redirect("back");
);

【讨论】:

谢谢,这也有效。 :)【参考方案2】:

尝试从数组中删除,标记为已更改并保存,就像这样

app.delete("/campgrounds/:id/comments/:comment_id", middleware.checkCommentOwnership, function(req, res)
// RESTful - DESTROY
Comment.findByIdAndRemove(req.params.comment_id, function(err)
    if(err)
        req.flash("error", "Uh Oh! Something went wrong.");
        res.redirect("/campgrounds");
    
    Campground.findById(req.params.id, function(err, campground)
        if(err)
            req.flash("error", "Uh Oh! Something went wrong.");
            res.redirect("/campgrounds");
        
            campground.comments.filter(comment => comment.toString() === 
                req.params.comment_id);
            campground.markModified('comments');
            campground.save(function(err)
            if(err)
                 req.flash("error", "Uh Oh! Something went wrong.");
                 res.redirect("/campgrounds");
                 return;
            
            req.flash("success", "Comment has been deleted!");
            res.redirect("back");
                )
        );
    );
);

【讨论】:

谢谢,这行得通。 :D

以上是关于节点/猫鼬 - 从数组中删除 ObjectId [重复]的主要内容,如果未能解决你的问题,请参考以下文章

从猫鼬中的数组中删除元素

猫鼬删除文档中的数组元素

节点猫鼬打字稿如何输入 type: ObjectId, ref: 'User'

Mongoose 删除(拉)数组中的文档,不适用于 ObjectID

猫鼬填充没有引用的 ObjectId 的通用数组

如何在猫鼬中分配一个objectid数组