Mongoose - 删除子文档数组项

11

我有一个针对用户的小架构:

{
 username: String,
 contacts: Array
}

例如,某些用户的联系人会像这样:

{
 username: "user",
 contacts: [{'id': ObjectId('525.....etc'), 'approved': false}, {'id':ObjectId('534.....etc'), 'approved': true}]
}

现在我需要从联系人中删除一个项目,所以我这样做:

model.findByIdAndUpdate(23, {'$pull': {
              'contacts':{'id':'525.....etc'}
              }});

但似乎没有起作用,没有错误,但它没有被删除,我只想将此文档返回给用户:

{
     username: "user",
     contacts: [{'id':ObjectId('534.....etc'), 'approved': false}]
    }

如何实现这个目标?

3个回答

17

$pull运算符实际上仅对其操作的数组元素执行条件。您的问题似乎并未实际显示您可能正在使用mongoose默认为所有数组字段创建的ObjectId值。

因此,您可以在导入ObjectId创建方法后像这样查询:

model.findByIdAndUpdate(23, {
    '$pull': {
        'contacts':{ '_id': new ObjectId(someStringValue) }
    }
});

实际上,您可以更好地定义“模式”,mongoose将基于模式中定义的“类型”自动转换ObjectId:

var contactSchema = new Schema({
    approved: Boolean
});

var userSchema = new Schema({
    username: String,
    contacts: [contactSchema]
});

这使得mongoose能够“遵循规则”,对于严格类型的字段定义。因此现在它知道你实际上对于联系人数组的每个元素都有一个_id字段,并且该字段的“类型”实际上是ObjectId,因此它将自动重新将提供的“String”值转换为真正的ObjectId。


嗨,谢谢,但现在我遇到了这个错误:**[MongoError: exception: cannot use the part (contacts of contacts.id) to traverse the element ({contacts: [ { id: ObjectId('543394bb964ac60915ceba8b'), approved: false }, { id: ObjectId('543399f9964ac60915ceba8c'), approved: false } ]})** 这是什么问题?我使用了你的点注释。 - itsme
@sbaaaang 你到底在做什么?你是否使用了“点表示法”形式,就像你被告知的那样?顺便说一句,感谢你清楚地显示出你的实际数据与你发布的数据不同,这可能是问题的一部分。请编辑以显示您的真实数据结构。 - Neil Lunn
是的,像你说的那样使用点符号,是的,我正在使用ObjectIds,但我想这不是问题:P 不是吗?(编辑后的问题) - itsme
好的,问题已经解决了,就像我在问题中发布的那样,只需要在查询时包装新的ObjectId(idContact)即可。谢谢!请编辑答案以便我接受它。 - itsme
1
要清楚的是,model.findByIdAndUpdate(23, {'$pull': { 'contacts':{'id': new ObjectId('525.....etc')} }}); 是有效的。 - itsme
@sbaaaang 应该更注意你正在使用mongoose。有一种特定的做事方式,你似乎不知道可以从中学到。当你执行显示的操作时,不需要手动“转换”。这就是为什么你应该在问题中发布你的“真实数据”和“查询”,不要虚构。 - Neil Lunn

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();            
    });

0
23在查询中是指数组中的位置还是指模型的编号?
model.findByIdAndUpdate(23, {
  '$pull': {
    'contacts':{ '_id': new ObjectId(someStringValue) }
  }
});

回答不清楚 这是一个回答还是一个问题?根据目前的写法,你的回答不清楚。请编辑以添加更多细节,帮助其他人理解这个回答如何解决所提出的问题。你可以在帮助中心找到关于如何撰写好的回答的更多信息。 - moken

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