删除许多文档时如何删除多个引用?

时间:2019-03-25 22:10:13

标签: javascript node.js mongodb express mongoose

我正在从“组件”集合中删除一个文档,该文档在“空间”集合中有引用。

从Component删除文档后,我从Space删除了对该文档的引用。

还有另一个集合“ ListItem”,“空间”中有对其的引用。在删除组件时,我想从“ ListItem”中删除数量不明的文档,然后从“ Space”中删除所有这些引用。我能够删除“ ListItem”中的文档,但不能删除Space中的引用。

我不知道该如何使用钩子。我现在知道,这仅适用于删除单个引用。如果我能以某种方式,对于要删除的ListItem实例,从Space.listItems中拉出ListItem.ListId,它可能有用吗? $ pullAll似乎是到目前为止我发现的最有希望的潜在解决方案。然后我必须查询Space并从Space.listItems中找到所有匹配的id并将它们存储在数组中?

ListItemsSchema.pre('deleteMany', function(next) {
    var list = this;
    var id = this.ListId;
    var spaceId = this.SpaceId;

    list.model('Space').update(
        { _id: spaceId},
        {$pull: {listItems: id}},
        {multi: true},
        next
    );
    // i'm removing ListItem.ListId from Space.listItems
})

在删除ListItems时,我不知道如何解决。同样的问题是pull方法错误。

router.delete('/DeleteComponent/:id', function(req, res) {

    let id = req.params.id;
    let spaceID = req.body.CurrentSpaceId;
    let listArray = [];

    Component.findOneAndRemove({ _id: id}).exec(function(err, removed) {
        Space.findOneAndUpdate(
            { _id: spaceID },
            { $pull: {components: id} },
            { new: true },
            function(err, removedFromSpace) {
                if (err) { console.log(err) }
                res.status(200).send(removedFromSpace);
            })
    });

    // delete all items where id == component/list id
    ListItem.deleteMany({ ListId: id}).exec(function(err, results) {
        if (err) {
            return console.log(err);
        } else {
            console.log("ListItems successfully removed.", results);
        }

        Space.update(
            { _id: spaceID},
            {$pull: {listItems: id}},
            {multi: true},
            function(err, removedFromSpace) {
                if (err) { console.log(err) }
                res.status(200).send(removedFromSpace);
            }
        );

    });
});

我已经尝试了其他一些方法,但这是迄今为止我最好的尝试。

Space的架构:

let spaceSchema = new mongoose.Schema({
  components: [{type: Schema.Types.ObjectId, ref: 'Component'}],
  listItems: [{type: Schema.Types.ObjectId, ref: 'ListItem'}],
});

组件的架构:

let componentSchema = new mongoose.Schema({
    ...
})

ListItem的架构:

let ListItemsSchema = new mongoose.Schema({

    ListItem: String,
    // ListId is equivalent to Component's _id
    ListId: String,
    SpaceId: String
});

预期结果是,当删除组件时,还将删除ListItems及其在Space中对它们的引用。目前,我无法完成删除Space中ListItems引用的最后一步。

1 个答案:

答案 0 :(得分:0)

我最终通过对数据库架构进行结构更改来解决了该问题,最终得到了一种更简洁,更优雅的解决方案。

我将引用listItems: [{type: Schema.Types.ObjectId, ref: 'ListItem'}]移到了componentSchema,因此,当删除一个组件时,对关联的ListItem文档的所有引用也都被删除了,而不必担心访问{{ 1}}或遍历值以动态创建数组。之后,Space与最近删除的组件的ID匹配的所有ListItem文档都将被删除。

ListItem.ComponentId

我在解决原始技术挑战方面也取得了进步。我的建议是找到一种方法来收集要从引用中删除的所有ID并将它们放入数组中,然后可以使用$pullAll从引用中删除它们:

// Delete component and remove from Spaces
router.delete('/DeleteComponent/:id', function(req, res) {

    let id = req.params.id;
    let spaceID = req.body.CurrentSpaceId;

    Component.findOneAndRemove({ _id: id}).exec(function(err, removed) {
        Space.findOneAndUpdate(
            { _id: spaceID },
            { $pull: {components: id} },
            { new: true },
            function(err, removedFromSpace) {
                if (err) { console.log(err) }
                res.status(200).send(removedFromSpace);
            })
    });

    // delete all items where id == component id
    ListItem.deleteMany({ ComponentId: id}).exec(function(err, results) {
        if (err) {
            return console.log(err);
        } else {
            console.log("ListItems successfully removed.", results);
        }

    });
});

但是,据我所知,除非您有充分的理由让您的引用以这种脱节的方式存在,否则使用更简单的解决方案尤其有意义,尤其是在使用MongoDB或任何其他非关系数据库。