Delete in cascade

I am currently having the following (forestadmin + mongodb):

User(s) -> [Has outfit(s)] -> Outfit(s) -> [List of item(s)/product(s)] -> Product(s)

We will, for the sake of this example, take only the Outfit model and the Product model. Here you can find two documents as a possible example (JSON Format):

// Outfit document
{
    "_id" : ObjectId("5eeb712dfa3a7b9028787903"),
    "picture_url" : "https://i.skyrock.net/3911/84063911/pics/3226492571_1_2_q8PvGEGD.jpg",
    "outfit_products_ids" : [ 
        ObjectId("5eeb712dfa3a7b9028787904"), 
        ObjectId("5eeb712dfa3a7b9028787905"), 
        ObjectId("5eeb712dfa3a7b9028787906"), 
        ObjectId("5eeb712dfa3a7b9028787907")
    ]
}

// Outfit Product Document
{
    "_id" : ObjectId("5eeb712dfa3a7b9028787905"),
    "outfit_id" : ObjectId("5eeb712dfa3a7b9028787903"),
    "title" : "Chemise bucheron, rouge/noir, a carreaux",
    "picture_url" : "https://www.projet13.com/9959-big_default/chemise-bucheron-rouge-noir-a-carreaux.jpg",
    "price" : NumberLong(4200),
    "redirect_url" : "https://www.projet13.com/6426-chemise-bucheron-rouge-noir-a-carreaux.html?gclid=Cj0KCQjwoaz3BRDnARIsAF1RfLfOJDZobj5gTT_uscskeyUqWgzZ_L2SJYvE_kMmk4weuzZpe-fc8cQaAr-IEALw_wcB#/10-taille-m/32-couleur-rouge"
}

Now, if we look at the forest admin part (model definitions), we have the following:

// Outfit Document
// This model was generated by Lumber. However, you remain in control of your models.
// Learn how here: https://docs.forestadmin.com/documentation/v/v6/reference-guide/models/enrich-your-models
const mongoose = require('mongoose');

// This section contains the properties of your model, mapped to your collection's properties.
// Learn more here: https://docs.forestadmin.com/documentation/v/v6/reference-guide/models/enrich-your-models#declaring-a-new-field-in-a-model
const schema = mongoose.Schema({ 
  'picture_url': String,
  'outfit_products_ids': { type: [mongoose.Schema.Types.ObjectId], ref: 'OutfitProductsCollection' },
}, {
  timestamps: false,
});

module.exports = mongoose.model('OutfitsCollection', schema, 'OutfitsCollection');
// Outfit Product Document
// This model was generated by Lumber. However, you remain in control of your models.
// Learn how here: https://docs.forestadmin.com/documentation/v/v6/reference-guide/models/enrich-your-models
const mongoose = require('mongoose');

// This section contains the properties of your model, mapped to your collection's properties.
// Learn more here: https://docs.forestadmin.com/documentation/v/v6/reference-guide/models/enrich-your-models#declaring-a-new-field-in-a-model
const schema = mongoose.Schema({ 
  'outfit_id': { type: mongoose.Schema.Types.ObjectId, ref: 'OutfitsCollection' },
  'title': String,
  'price': Number,
  'redirect_url': String,
  'picture_url': String,
}, {
  timestamps: false,
});

module.exports = mongoose.model('OutfitProductsCollection', schema, 'OutfitProductsCollection');

Expected behavior

Now that I have my belongsTo and hasMany setup, I would like the following behavior:

  • Removing an outfit leads to remove the related outfit products
  • Removing an Outfit Product leads to remove an id ($pull) from the outfit_products_ids of the related outfit ($belongsTo -> outfit_id)

Question

Is this feature exist in forestadmin?

Thanks

Hi @Thomas :wave:

Since forest admin agent relies on mongoose, ou could try to use the mongoose’s pre (or post) remove middleware on your models. You could find more info here:

One other approach would be to override the delete and delete many routes and add your logic here using classic mongoose queries. See how to override routes middleware in Forest Admin documentation.

Let me know if you find your way in creating your cascade logic, otherwise, I could try to help you creating it!

Hey,

Ok I will look at it and come back to you once i work on it!

thanks,

max

1 Like

Hey,

I did start to look at it but neither post nor pre seems to be part of schema object:

// This model was generated by Lumber. However, you remain in control of your models.
// Learn how here: https://docs.forestadmin.com/documentation/v/v6/reference-guide/models/enrich-your-models
const mongoose = require('mongoose');

// This section contains the properties of your model, mapped to your collection's properties.
// Learn more here: https://docs.forestadmin.com/documentation/v/v6/reference-guide/models/enrich-your-models#declaring-a-new-field-in-a-model
const schema = mongoose.Schema({
    'picture_url': String,
    'outfit_products_ids': {type: [mongoose.Schema.Types.ObjectId], ref: 'OutfitProductsCollection'},
    'user_id': {type: mongoose.Schema.Types.ObjectId, ref: 'CertifiedUsersCollection'},
}, {
    timestamps: false,
});

schema.post('remove', function (doc) {
    console.log("test?" + doc);
});

module.exports = mongoose.model('OutfitsCollection', schema, 'OutfitsCollection');

I have no output neither, I will try to override the RecordsRemover route

Hi :slight_smile:

I am now trying to extend my route (remove many) but I don’t understand how getIdsFromRequest is getting the ids from the request.

I actually would like to get outfits_products_ids array from the removed documents in order to call another route from my current route (from removeMany of the first collection, maybe I could call the removeMany of the second collection?)

Thanks

Hi @Thomas :wave: if I understand correctly you try to remove one or many collection and all the products associated on each collection right ?
If the post or pre hook doesn’t work you need to be careful :
This route is called up when you select more than one record.

router.delete('/collections'

And this one is called if you select only one record

router.delete('/collections/:recordId'

In case of many record selected, you should call

new RecordsGetter(collections).getIdsFromRequest(request)
    .then((ids) => {
      // ids here are the ids of all the collection selected(the ones you want to delete)
    }

You can after that remove all product associated to each collection

products.deleteMany({ collection_id: { $in: ids }});

And finally remove all the collections.

Don’t forget to adapt the behavior on the single delete route.

Let me know if it help.

1 Like