DEV Community

Emeka Okwor
Emeka Okwor

Posted on

7 1

Dynamic Model Referencing with Mongoose

So, I had a mongoose schema that referenced multiple collections. I wanted a situation where I could populate the schema from these collections depending on the property value in the document. Did I confuse you? Oh, my bad, I'd give you a logical example.
Say we have a comment schema, and a user can comment on a blog post and a product. How can we populate the schema with the blog post comments or product comments programmatically? Well, now you see what I mean, right?.
It appears there is something called refPath. The refPath option is a more sophisticated alternative to ref. If ref is just a string, mongoose will always query the same model to find the populated sub documents. With refPath, you can configure what model Mongoose uses for each doc. It automatically instructs mongoose to look into an 'onModel' property to find the correct model to populate. For example, let's say we have a comment schema like so

const commentSchema = new Schema({
  body: { type: String, required: true },
  on: {
    type: Schema.Types.ObjectId,
    required: true,
    refPath: 'onModel'
  },
  onModel: {
    type: String,
    required: true,
    enum: ['BlogPost', 'Product']
  }
});

Enter fullscreen mode Exit fullscreen mode

Notice the property 'onModel'?. It defines the name of our models "BlogPost" and "Product" referenced in the schema like sorefpath:'onModel'.

Now, Let's create our models and add some data


// create models
const Product = mongoose.model('Product', new Schema({ name: String }));

const BlogPost = mongoose.model('BlogPost', new Schema({ title: String }));

const Comment = mongoose.model('Comment', commentSchema);

// add data to collections
const book = await Product.create({ name: 'The Count of Monte Cristo' });

const post = await BlogPost.create({ title: 'Top 10 French Novels' });

const commentOnBook = await Comment.create({
  body: 'Great read',
  on: book._id,
  onModel: 'Product'
});

const commentOnPost = await Comment.create({
  body: 'Very informative',
  on: post._id,
  onModel: 'BlogPost'
});


Enter fullscreen mode Exit fullscreen mode

We can query the comment schema, populate it with the data of a particular model we specified like so

const comments = await Comment.find().populate({ path: "BlogPost"})

Enter fullscreen mode Exit fullscreen mode

when you log comments, you should see something like this

// [ { _id: ....., on: { title: 'Top 10 French Novels' } }]

Enter fullscreen mode Exit fullscreen mode

Cool, init? I hope it helps someone out there. Happy coding.

Neon image

Build better on Postgres with AI-Assisted Development Practices

Compare top AI coding tools like Cursor and Windsurf with Neon's database integration. Generate synthetic data and manage databases with natural language.

Read more →

Top comments (0)

👋 Kindness is contagious

Dive into this informative piece, backed by our vibrant DEV Community

Whether you’re a novice or a pro, your perspective enriches our collective insight.

A simple “thank you” can lift someone’s spirits—share your gratitude in the comments!

On DEV, the power of shared knowledge paves a smoother path and tightens our community ties. Found value here? A quick thanks to the author makes a big impact.

Okay