如何使用mongoose从数组中删除对象

19

我正在尝试使用mongoose从文档中的数组中删除一个对象。

模式如下:

var diveSchema = new Schema({
//irrelevant fields
    divers: [{
        user: { type: Schema.Types.ObjectId, ref: 'User', required: true },
        meetingLocation: { type: String, enum: ['carpool', 'onSite'], required: true },
        dives: Number,
        exercise: { type: Schema.Types.ObjectId, ref: 'Exercise' },
    }]
});

可能的一个入口可以是

{
    //irrelevant fields
    "divers": [
        {
            "_id": "012345678",
            "user": "123456789",
            "meetingLocation": "carpool",
            "exercise": "34567890",
        },
        {
            "_id": "012345679",
            "user": "123456780",
            "meetingLocation": "onSite",
            "exercise": "34567890",
        }
    ]
}

假设我想删除 user123456789 的记录(注意,此时我不知道 _id 是什么)。

我该如何正确地执行此操作?

我尝试了以下方法:

        var diveId = "myDiveId";
        var userIdToRemove = "123456789"
        Dive.findOne({ _id: diveId }).then(function(dive) {
            dive.divers.pull({ user: userIdToRemove });
            dive.save().then(function(dive) {
                //do something smart
            });
        });
此方法未对文档产生任何更改。

我还尝试了

Dive.update({ _id: diveId }, { "$pull": { "divers": { "diver._id": new ObjectId(userIdToRemove) } } }, { safe: true }, function(err, obj) {
    //do something smart
});

通过这个操作,我得到的结果是给定潜水中整个 divers 数组被清空了。

5个回答

38

这个怎么样?

Dive.update({ _id: diveId }, { "$pull": { "divers": { "user": userIdToRemove } }}, { safe: true, multi:true }, function(err, obj) {
    //do something smart
});

这好像行了!谢谢,但是您能否解释一下我做错了什么,因为我之前尝试使用了 user,但没有添加 multi 部分。 - Sonaryr
1
当您有一个查询单个文档 { _id: diveId } 的更新操作时,选项 { safe: true, multi:true } 如何有帮助? - chridam
@chridam,你说得对,对于单个文档和$pull操作,使用multi:true会过度杀伤力,但老实说,我遇到过一些驱动程序,如果你不将multi设置为true,它们就会在执行一个操作(而不是文档)后停止执行。例如,如果你在数组中调用$set,某些驱动程序只会设置数组的第一个元素。这就是我使用它的原因。你可以避免使用它。 - Rahul Kumar
@Sonaryr 如果你尝试了相同的查询,也许它没有起作用的原因在于我的先前评论中提到的,这基本上归结于你的驱动程序如何实现操作。 - Rahul Kumar

5
我使用以下代码解决了这个问题-
 await Album.findOneAndUpdate(
    { _id: albumId },
    { $pull: { images: { _id: imageId } } },
    { safe: true, multi: false }
  );
  return res.status(200).json({ message: "Album Deleted Successfully" });

这太棒了。它对我有用。 - Minhaz

0

尝试一下这段异步代码

var diveId = "myDiveId";
var userIdToRemove = "123456789"
const dive=await Dive.findOne({ _id: diveId })
await dive.divers.pull({ user: userIdToRemove });
await dive.save();

1
欢迎来到 Stack Overflow!如果您解释一下为什么这个答案可行,或者为什么这个解决方案比已经存在一段时间的现有答案更好,那么您的回答可能对其他人更有帮助 :) - user14518353

0

试试这个

Dive.update({_id: diveId}, {"$pull": {"drivers": {"user": "123456789"}}})


1
与上面相同的答案。 - Hola Soy Edu Feliz Navidad

0

使用try/catch结构:

await Group.updateOne(
  { _id: groupId },
  { $pull: { members: {id: memberId }}}
);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接