Mongoose - 删除子文档数组项

Posted

技术标签:

【中文标题】Mongoose - 删除子文档数组项【英文标题】:Mongoose - delete subdocument array item 【发布时间】:2014-12-02 20:35:10 【问题描述】:

我有这个供用户使用的小架构:


 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]
    

如何做到这一点?

【问题讨论】:

【参考方案1】:

$pull 运算符实际上只是对它所操作的数组元素执行条件。看来您的问题实际上可能并未表明您可能正在使用 mongoose 默认为所有数组字段创建的 ObjectId 值。

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

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

或者实际上你可以更好地定义你的“模式”,猫鼬实际上会根据模式中定义的“类型”为你“自动转换”ObjectId:

var contactSchema = new Schema(
    approved: Boolean
);

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

这允许 mongoose 为严格类型的字段定义“遵循规则”。所以现在它知道你实际上为contacts数组的每个元素都有一个_id字段,并且该字段的“类型”实际上是一个ObjectId,所以它会自动重新转换“字符串”值作为真正的 ObjectId 提供。

【讨论】:

嗨,谢谢,但现在我收到了这个错误:[MongoError: exception: cannot use the part (contacts of contacts.id) to traverse the element (contacts: [ id: ObjectId( '543394bb964ac60915ceba8b'), 批准: false , id: ObjectId('543399f9964ac60915ceba8c'), 批准: false ]) 这可能是什么?我用了你的点注释—— @sbaaaang 你到底在做什么?您是否按照您的要求使用“点符号”形式?顺便说一句,感谢您清楚地表明您的实际数据与您发布的方式不同,这可能又是问题的一部分。请编辑以显示您的真实数据结构。 是的,使用 dot notation 就像你说的那样,是的,我正在使用 ObjectIds 但我猜这不是问题:P 不是吗? (已编辑问题) 好的修复了它,因为我发布的问题只需要在查询时包装新的 ObjectId(idContact) ;) 谢谢!请编辑答案,以便我接受它 要明确 model.findByIdAndUpdate(23, '$pull': 'contacts':'id': new ObjectId('525.....etc') ); 工作【参考方案2】:

终于!

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

【讨论】:

以上是关于Mongoose - 删除子文档数组项的主要内容,如果未能解决你的问题,请参考以下文章

阻止 Mongoose 为子文档数组项创建 _id 属性

阻止 Mongoose 为子文档数组项创建 _id 属性

阻止 Mongoose 为子文档数组项创建 _id 属性

阻止 Mongoose 为子文档数组项创建 _id 属性

阻止 Mongoose 为子文档数组项创建 _id 属性

阻止 Mongoose 为子文档数组项创建 _id 属性