Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't solve circular dependency of mongoose models

I have 3 models, Book & Author & 'Category'. Author can have multiple books. Category can have multiple books and Book can't be created without a valid Author or Category

const schema = new mongoose.Schema(
  {
    title: dbHelpers.bookTitleValidation,
    image: dbHelpers.imageValidation,
    author: dbHelpers.bookAuthorValidation,
    category: dbHelpers.categoryValidation,
    reviews: [dbHelpers.bookReviewValidation],
    rates: [dbHelpers.bookRateValidation],
  },
  { timestamps: true }
);

What I want to do is:

  • when trying to save a new book, I should validate that the associated author & category are valid, So I created a pre "save" middleware to validate this [in Book model before exporting the model].
  • when deleting an author or category, all associated books should be deleted, So again I created a pre "remove" middleware to achieve this [in Author & category models before exporting the model].

This is the pre 'save' middleware in Book model

schema.pre("save", async function (next) {
  const author = await authorModel.findById(this.author);
  if (!author) {
    next(new Error("Author is not valid!"));
  }

  const category = await categoryModel.findById(this.category);
  if (!category) {
    next(new Error("Category is not valid!"));
  }

  next();
});

And This is the pre 'remove' middleware in Author model

schema.pre("remove", { document: true }, async function (next) {
  await booksModel.find({ author: this.id }).remove();

  let imgFileName = this.image.split("/")[3];
  console.log("imgFileName: ", imgFileName);

  await rm(__dirname + "/../" + "public/authors/" + imgFileName + ".png");

  next();
});

The issue is to make these middelwares work, I have to do the following [this is the way i know]:

  • const booksModel = require("./Book"); //in Author model
  • const authorModel = require("./Author"); // in books model

This gives me an empty object for authorModel, after searching about it I found that this is due to the circular dependency.

How can I fix this and still using these middlewares?

like image 521
Atef H. Avatar asked Oct 25 '25 01:10

Atef H.


1 Answers

I solved this by not requiring the models into each others.

To access a mongoose model, I used this way:

mongoose.model('MODEL_NAME').something

In this manner I was able to remove the circular dependency and still access the models.


Reference:

Hard solution: use a dependency injector. Easy solution: if you create a model using mongoose.model('Message', MessageSchema); you can then access the model with mongoose.model('Message');, so all you need to do is require('mongoose'); in the file to access your models.

https://github.com/Automattic/mongoose/issues/3826#issuecomment-178047542

like image 126
Atef H. Avatar answered Oct 26 '25 16:10

Atef H.



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!