Open In App

How to Join two Schemas in Mongoose?

Last Updated : 23 Jul, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Mongoose is a popular MongoDB object modeling tool for Node.js that simplifies data manipulation. However, developers often face challenges when trying to join two schemas in Mongoose, as MongoDB, a NoSQL database, does not natively support join operations like SQL databases. In this article, We will learn about How to join two schemas in Mongoose in detail.

How to join two schemas in Mongoose?

Mongoose is a MongoDB object modeling tool for Node.js that simplifies data manipulation in MongoDB. However, one of the keen challenges developers face is how to effectively join two schemas in Mongoose. Unlike SQL databases, MongoDB, being a NoSQL database, does not natively support join operations. Here we will discuss below 2 methods that help us to join two schemas in Mongoose

  1. Using Population Method
  2. Using the aggregate() Method with $lookup

Understanding Mongoose Schemas

Before seeing the joining techniques, it's essential to understand what schemas are in Mongoose. A schema defines the structure of documents within a collection. It provides the blueprint for how data is stored, specifying field names, data types, and validation requirements.


const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const userSchema = new Schema({
  name: String,
  email: String,
});

const NonUserSchema = new Schema({
  title: String,
  content: String,
  author: { type: Schema.Types.ObjectId, ref: 'User' },
});

const User = mongoose.model('User', userSchema);
const Post = mongoose.model('Post', NonUserSchema);

In the example above, we have two schemas: User and Post. The Post schema has a field author which references the User schema.

author: { type: Schema.Types.ObjectId, ref: 'User' },

1. Population Method

Population is one of the efficient method in Mongoose that allows you to refer the documents in other collections. It is equivalent to performing a join operation in a relational database such as MySQL.

Lets see the steps involved in the population method to join two schemas.

Step 1:

Define the Schemas with References. Use the ref option inside a schema to refer another schema in the document.

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const userSchema = new Schema({
  name: String,
  email: String,
});

const postSchema = new Schema({
  title: String,
  content: String,
  author: { type: Schema.Types.ObjectId, ref: 'User' },
});

const User = mongoose.model('User', userSchema);
const Post = mongoose.model('Post', postSchema);

Step 2:

Create and save documents to both collections so that we can perform merging both schemas.

const user = new User({ name: 'Pravin Raju', email: '[email protected]' });
user.save((err) => {
  if (err) return console.error(err);

  const post = new Post({
    title: 'GoodMorning Sir',
    content: 'This is my first post!',
    author: user._id,
  });

  post.save((err) => {
    if (err) return console.error(err);
  });
});

Step 3:

Use the populate method to replace the author field in the Post document with the actual User document. The populate method fetches the User document referenced by the author field and includes it in the query result.


Post.findOne({ title: 'GoodMorning Sir' })
  .populate('author')
  .exec((err, post) => {
    if (err) return console.error(err);
    console.log(post);
  });

Output:


[
  {
    "_id": "60c72b2f5f1b2c001c8e4a2c",
    "title": "GoodMorning Sir",
    "content": "This is the content",
    "author": {
      "_id": "60c72b2f5f1b2c001c8e4a2b",
      "name": "Pravin Raju",
      "email": "[email protected]"
    }
  }
]

Explanation: After executing the populate method, the author field in the Post documents will be populated with the corresponding User documents. The result will look something like this JSON like Format below:

2. Using the aggregate() Method with $lookup

The Aggregation Framework in MongoDB provides powerful data processing capabilities, including the $lookup stage to perform joins. This method is also reffered to as the embedding method, where the embedding involves directly including the data of one document within another document. This method can be more efficient for read operations but may lead to data redundancy Here is how to use the aggregate() method with $lookup to join two schemas:

Step 1:

Define the schema:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const commentSchema = new Schema({
  content: String,
  date: { type: Date, default: Date.now },
});

const postSchema = new Schema({
  title: String,
  content: String,
  comments: [commentSchema],
});

const Post = mongoose.model('Post', postSchema);

Step 2:

Create and Save Documents

const user = new User({ name: 'Pravin Raju', email: '[email protected]' });
user.save((err) => {
  if (err) return handleError(err);

  const post = new Post({ title: 'GoodMorning Sir', content: 'This is the content', author: user._id });
  post.save((err) => {
    if (err) return handleError(err);
    // Documents saved
  });
});

Step 3:

Use the aggregate() Method with $lookup:

Post.aggregate([
  {
    $lookup: {
      from: 'users', // collection name in MongoDB
      localField: 'author',
      foreignField: '_id',
      as: 'authorDetails'
    }
  },
  {
    $unwind: '$authorDetails'
  }
]).exec((err, posts) => {
  if (err) return handleError(err);
  console.log(posts);
});

Output:

[
  {
    "_id": "60c72b2f5f1b2c001c8e4a2c",
    "title": "GoodMorning Sir",
    "content": "This is the content",
    "author": {
      "_id": "60c72b2f5f1b2c001c8e4a2b",
      "name": "Pravin Raju",
      "email": "[email protected]"
    }
  }
]

Explanation: The aggregate method with $lookup performs a join between the Post and User collections, embedding the User document inside the Post document under the authorDetails field. The result will look something like this:

Conclusion

Joining two schemas in Mongoose can be effectively achieved using population or embedding. Each method has its own advantages and disadvantages. Population is more flexible and reduces data redundancy, while embedding offers better read performance and data locality.

By understanding your application's requirements, you can choose the appropriate method to manage relationships between schemas in Mongoose. By following these steps, you can efficiently manage relationships between schemas in your Mongoose and MongoDB applications

To learn more about the basic operation in MongoDB, do refer the article inside this link.


Article Tags :

Similar Reads