Как удалить несколько ссылок при удалении большого количества документов? - PullRequest
0 голосов
/ 26 марта 2019

Я удаляю документ из коллекции «Компонент», на который есть ссылки в коллекции «Пространство».

После удаления документа из Компонента я удаляю ссылку на этот документ из Пространства.

Существует еще одна коллекция «ListItem», на которую есть ссылки в «Space».Когда я удаляю Компонент, я хочу удалить неизвестное количество документов из «ListItem», а затем удалить все эти ссылки из «Space».Мне удалось удалить документы внутри ListItem, но не ссылки в Space.

Я не мог понять, как использовать с этим хуки.Теперь я понимаю, что это будет работать только для удаления одной ссылки.Если бы я мог как-то, для каждого экземпляра ListItem, который удаляется, вытащить ListItem.ListId из Space.listItems, это могло бы работать?$ pullAll представляется наиболее перспективным потенциальным решением, которое я нашел до сих пор.Тогда мне нужно будет запросить Space и найти все соответствующие идентификаторы из Space.listItems и сохранить их в массиве?

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

    });
});

Я пробовал еще несколько вещей, но это были мои лучшие попытки до сих пор.

Схема пространства:

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.В настоящее время я не могу сделать последний шаг по удалению ссылок для ListItems в пространстве.

1 Ответ

0 голосов
/ 26 марта 2019

Я решил эту проблему, внеся структурные изменения в схемы базы данных, и в результате получил более чистое и элегантное решение.

Я переместил ссылки listItems: [{type: Schema.Types.ObjectId, ref: 'ListItem'}] на componentSchema, поэтому при удалении компонента все ссылки на связанные документы ListItem также удаляются, не беспокоясь о доступе к Space или перебирая значения в динамически создавать массивы. После этого все ListItem документы, в которых ListItem.ComponentId соответствует идентификатору недавно удаленного компонента, удаляются.

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

    });
});

Я также продвинулся в решении оригинальной технической задачи. Я предлагаю найти способ собрать все идентификаторы, которые вы хотите удалить из ссылки, и поместить их в массив, а затем вы можете использовать $ pullAll , чтобы удалить их из ссылок:

let myIdsArray = [id1, id2, id3];
Collection.update( {_id: id}, { $pullAll: {field: myIdsArray } } );

Однако, насколько я могу судить, если у вас нет очень веских причин для того, чтобы ваши ссылки существовали таким отсоединенным способом, имеет смысл использовать гораздо более простое решение, особенно при использовании MongoDB или любого другого реляционная база данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...