2

I have these 3 models in mongoose:

TravelSchema

var travelSchema = new mongoose.Schema({
    name: String,
    description: String,
    mexican_currency_value: mongoose.Schema.Types.Decimal128
})

travelSchema.pre('deleteOne', function(next) {
    const id = this.getQuery()['_id'];
    Product.deleteMany({ travel: id }, (err, value) => {
    });
    next();    
});

ProductSchema

var productSchema = new mongoose.Schema({
    name: String,
    description: String,
    purchased_amount: Number,
    unit_price_mex: mongoose.Schema.Types.Decimal128,
    unit_price_to_sell: mongoose.Schema.Types.Decimal128,
    travel: { type: mongoose.Schema.Types.ObjectId, ref: 'Travel' }
})

InvoiceSchema

var invoiceSchema = new mongoose.Schema({
    product: productSchema,
    client: { type: mongoose.Schema.Types.ObjectId, ref: 'Client' },
    purchased_amount: Number,
    fch: String
});

Where Travel and Product have a one-to-many relationship and Product and Invoice have a one-to-many relationship. I need the following:

  • When a Travel is deleted, all Products that are related to that Travel are also deleted.

  • When these Products are eliminated, all the Invoices related to each Product are also eliminated.

I have managed to eliminate all the products, but when I try to eliminate the invoices I do not obtain the ids of the Products.

invoiceSchema.pre('deleteMany', (next) => {
    console.log(this);
    // this print { n: 2, ok: 1, deletedCount: 2 }
})
  • Possible duplicate of https://stackoverflow.com/questions/14348516/cascade-style-delete-in-mongoose – kevinadi Jun 21 '19 at 05:18
  • No, it's not the same. You should read well again. – Leandro Hernández Mira Jun 21 '19 at 13:13
  • Hi, when you've defined `productSchema` you establish the relationship again `travelSchema` like this: `travel: { type: mongoose.Schema.Types.ObjectId, ref: 'Travel' }`, however in `invoiceSchema` you relationship with product is defined `product: productSchema`. If both relationship are one-to-many, why have you defined each with a different approach? Is this necessary? Have you tried define both relationships with the same approach? – Raydel Miranda Jun 21 '19 at 14:31
  • There are two types of ways to create relationships. Embedded or Referential. In my case Invoice-Product I need to be embedded, but Travel-Product is better referential. – Leandro Hernández Mira Jun 21 '19 at 14:39
  • So the real question is, how to obtain the ids (for cascading deletion) for documents related using the embedded schema approach when deleting? It seems the issue is with the embedded schema. – Raydel Miranda Jun 21 '19 at 20:51

1 Answers1

1

I think you should start the other way when looking at deleting all the related docs. Like you have travel id, with it get all the products and store their id in array and then your first delete should be of the invoices where product._id: { $ in: _arrayOfProducIds }. Once that is complete then deleteMany your products since you already have their ids in the _arrayOfProducIds and lastly deal with the Travel:

travelSchema.pre('deleteOne', function(next) {
    const id = this.getQuery()['_id'];  // travel id check
    // Query to get all the product ids based on the travel id and return array for `$in`
    const productIds = this.DoYourQuery  // [productIds] check
    Invoice.deleteMany({'product._id': { $in: productIds }}, // ... etc
    Product.deleteMany({ _id': { $in: productIds }}, // ... etc
    next();    
});

I would assume you do not have a large number of products and invoices ... like thousands since then $in might be somewhat of a performance issue. Hope this helps.

Akrion
  • 18,117
  • 1
  • 34
  • 54