【问题标题】:Mongoose delete array element in document and save猫鼬删除文档中的数组元素并保存
【发布时间】:2013-01-23 16:43:05
【问题描述】:

我的模型文档中有一个数组。我想根据我提供的键删除该数组中的元素,然后更新 MongoDB。这可能吗?

这是我的尝试:

var mongoose = require('mongoose'),
    Schema = mongoose.Schema;

var favorite = new Schema({
    cn: String,
    favorites: Array
});

module.exports = mongoose.model('Favorite', favorite, 'favorite');

exports.deleteFavorite = function (req, res, next) {
    if (req.params.callback !== null) {
        res.contentType = 'application/javascript';
    }
    Favorite.find({cn: req.params.name}, function (error, docs) {
        var records = {'records': docs};
        if (error) {
            process.stderr.write(error);
        }
        docs[0]._doc.favorites.remove({uid: req.params.deleteUid});

        Favorite.save(function (error, docs) {
            var records = {'records': docs};
            if (error) {
                process.stderr.write(error);
            }
            res.send(records);

            return next();
        });
    });
};

到目前为止,它找到了文档,但删除或保存都有效。

【问题讨论】:

    标签: node.js mongoose


    【解决方案1】:
    Favorite.update({ cn: req.params.name }, { "$pull": { "favorites": { "_id": favoriteId } }}, { safe: true, multi:true }, function(err, obj) {
        //do something smart
    });
    

    【讨论】:

      【解决方案2】:

      您也可以直接在 MongoDB 中进行更新,而无需加载文档并使用代码对其进行修改。使用 $pull$pullAll 运算符从数组中删除项目:

      Favorite.updateOne({ cn: req.params.name }, {
          $pullAll: {
              favorites: req.params.deleteUid,
          },
      });
      

      从数组中移除对象

      Favorite.updateOne({ cn: req.params.name }, {
          $pullAll: {
              favorites: [{_id: req.params.deleteUid}],
          },
      });
      

      (您也可以对多个文档使用 updateMany)

      http://docs.mongodb.org/manual/reference/operator/update/pullAll/

      【讨论】:

      • 我不明白这是如何在不引用名称收藏夹的情况下从收藏夹数组(子数组而不是文档)中删除项目
      • 这个操作也是原子的。这意味着文档不会在单独的查找和更新操作之间发生变化。
      • 谢谢!非常优雅的解决方案。
      • @Dominic 现在添加了favourites。我不敢相信这被忽视了 6 年多
      【解决方案3】:

      我在我的项目中使用了这种格式,并且成功了

      router.delete('/dashboard/participant/:id', async (req, res, next) => {
          try {
              const participant = await Participant.findByIdAndDelete({ _id: req.params.id });
              // { $pull: { templates: { _id: templateid } } },
              const event = await Event.findOneAndUpdate({ participants: participant._id }, { $pull: { participants: participant._id } }, { new: true });
              res.status(200).json({ request: 'Deleted', participant, event });
          } catch (error) {
              res.json(error)
          }
      });
      

      【讨论】:

        【解决方案4】:

        选中的答案确实有效,但在 MongooseJS 最新版本中,您应该使用 pull

        doc.subdocs.push({ _id: 4815162342 }) // added
        doc.subdocs.pull({ _id: 4815162342 }) // removed
        

        https://mongoosejs.com/docs/api.html#mongoosearray_MongooseArray-pull

        我也在查。

        请参阅丹尼尔的答案以获得正确答案。好多了。

        【讨论】:

        • @LondonRob +1 做了一个很好的编辑,我们应该注意不要使用不安全的链接。
        • 这就是我需要的!它干净且易于使用在另一个模型中作为参考的 id
        【解决方案5】:

        上面的答案显示了如何删除数组,这里是如何从数组中拉出对象。

        参考:https://docs.mongodb.com/manual/reference/operator/update/pull/

        db.survey.update( // select your doc in moongo
            { }, // your query, usually match by _id
            { $pull: { results: { $elemMatch: { score: 8 , item: "B" } } } }, // item(s) to match from array you want to pull/remove
            { multi: true } // set this to true if you want to remove multiple elements.
        )
        

        【讨论】:

        • 在使用这个例子时请小心,它在某些情况下可能不起作用,正如上面的文档In fact, the following operation will not pull any element from the original collection. 中提到的那样。阅读上面的文档了解更多详细信息。
        【解决方案6】:

        这对我有用,真的很有帮助。

        SubCategory.update({ _id: { $in:
                arrOfSubCategory.map(function (obj) {
                    return mongoose.Types.ObjectId(obj);
                })
            } },
            {
                $pull: {
                    coupon: couponId,
                }
            }, { multi: true }, function (err, numberAffected) {
                if(err) {
                    return callback({
                        error:err
                    })
                }
            })
        });
        

        我有一个名为SubCategory 的模型,我想从这个类别数组中删除优惠券。我有一系列类别,所以我使用了arrOfSubCategory。所以我在 $in 运算符的帮助下,使用 map 函数从这个数组中获取每个对象数组。

        【讨论】:

          【解决方案7】:
          keywords = [1,2,3,4];
          doc.array.pull(1) //this remove one item from a array
          doc.array.pull(...keywords) // this remove multiple items in a array
          

          如果你想使用...,你应该在你的js文件顶部调用'use strict';; :)

          【讨论】:

            【解决方案8】:

            由于收藏夹是一个数组,所以只需将其拼接起来保存文档即可。

            var mongoose = require('mongoose'),
                Schema = mongoose.Schema;
            
            var favorite = new Schema({
                cn: String,
                favorites: Array
            });
            
            module.exports = mongoose.model('Favorite', favorite);
            
            exports.deleteFavorite = function (req, res, next) {
                if (req.params.callback !== null) {
                    res.contentType = 'application/javascript';
                }
                // Changed to findOne instead of find to get a single document with the favorites.
                Favorite.findOne({cn: req.params.name}, function (error, doc) {
                    if (error) {
                        res.send(null, 500);
                    } else if (doc) {
                        var records = {'records': doc};
                        // find the delete uid in the favorites array
                        var idx = doc.favorites ? doc.favorites.indexOf(req.params.deleteUid) : -1;
                        // is it valid?
                        if (idx !== -1) {
                            // remove it from the array.
                            doc.favorites.splice(idx, 1);
                            // save the doc
                            doc.save(function(error) {
                                if (error) {
                                    console.log(error);
                                    res.send(null, 500);
                                } else {
                                    // send the records
                                    res.send(records);
                                }
                            });
                            // stop here, otherwise 404
                            return;
                        }
                    }
                    // send 404 not found
                    res.send(null, 404);
                });
            };
            

            【讨论】:

            • 感谢您的详尽回复。
            • 如果您尝试同时删除 2 个东西,它们都可能会获取数组,然后更改它,并且保存的第一个更改会被第二个更改覆盖。我宁愿这样stackoverflow.com/questions/16959099/…
            猜你喜欢
            • 2020-06-10
            • 2014-08-03
            • 1970-01-01
            • 2018-05-28
            • 2016-01-24
            • 2019-06-06
            • 1970-01-01
            • 2016-07-30
            • 2020-12-18
            相关资源
            最近更新 更多