Populate in Mongoose: Comprehensive Guide

Populate In Mongoose Featured Image

In this tutorial, I will give you a detailed walkthrough on how you can use populate in Mongoose in a Nodejs application.

Populate in Mongoose is used to enhance one-to-many or many-to-one data relationships in MongoDB. The populate() method allows developers to simply refer to a document inside a different collection to another document’s field that resides in a different field.

It lets you set the field’s value as the actual document that you are referring to. For instance, you are making a Reddit or Twitter clone. You have users on it and you want to integrate a commenting feature for them. So, to identify who made the comment and do actions on it, you will need some relationship between the user and the comments made by him/her, right? Well, this is where populate in Mongoose comes into play.

This guide shall walk you through a perfect example as to how you can use populate in Mongoose from scratch.

Populate in Mongoose – Quick Step-by-Step Guide

We will create a small application for learning to use populate in Mongoose.

Prerequisites

  • Beginner-level knowledge of Nodejs
  • Beginner-level knowledge of MongoDB
  • Beginner-level knowledge of Mongoose
  • Have installed Nodejs and MongoDB on your machine

Assuming you fulfill the above prerequisites, l will now move forward to create our Nodejs application to learn to populate in Mongoose.

Creating a Nodejs Application & Installing Packages

We are creating a farm stand application where we have two collections; one for farms and the other for the products sold by those farms.

  • Open a Bash terminal and create a new project directory and move into it:
mkdir farmApp

cd farmApp
  • Initialize a Nodejs project inside the directory and create the entry point file:
npm init -y

touch index.js
  • Install all the necessary packages for the project:
npm i mongoose

Configuring Packages, Schemas, & Models

Let us now flip over to our code editor and open up our project and follow the further steps of this tutorial on populating in Mongoose.

  • In index.js file, require all packages:
const express = require('express');

const mongoose = require('mongoose');

const { Schema } = mongoose; // To get access to mongoose.Schema
  • Set up connection to MongoDB using Mongoose:
mongoose.connect('mongodb://localhost:27017/farmStandTake2', { useNewUrlParser: true, useUnifiedTopology: true })
    .then(() => {
        console.log("MONGO CONNECTION OPEN!!!")
    })
    .catch(err => {
        console.log("OH NO MONGO CONNECTION ERROR!!!!")
        console.log(err)
    })
  • Create schemas for both farms and products:

FarmSchema and model:

const farmSchema = new Schema({
    name: {
        type: String,
        required: [true, 'Farm must have a name!']
    },
    city: {
        type: String
    },
    email: {
        type: String,
        required: [true, 'Email required']
    },
    products: [
        {
            type: Schema.Types.ObjectId,
            ref: 'Product'
        }
    ]
});

const Farm = mongoose.model('Farm', farmSchema);

Products schema and model:

const productSchema = new Schema({
    name: {
        type: String,
        required: true
    },
    price: {
        type: Number,
        required: true,
        min: 0
    },
    category: {
        type: String,
        lowercase: true,
        enum: ['fruit', 'vegetable', 'dairy']
    },
    farm: {
        type: Schema.Types.ObjectId,
        ref: 'Farm'
    }
});

const Product = mongoose.model('Product', productSchema);

Let us take a look at one of our farms that we just created:

{
  products: 6170854b496fcd1b541f5b1a,
  _id: 6170847b496fcd1b541f5b19,
  name: "Giovanni's Wheat Fields",
  city: 'Marzamemi, Sicily',
  email: 'giovanniswheat@myfarms.com',
  __v: 0
}

And, this is what our product looks like:

{
  _id: 6170854b496fcd1b541f5b1a,
  name: 'Whole Wheat Grains',
  price: 1,
  category: 'vegetable',
  farm: 6170847b496fcd1b541f5b19,
  __v: 0
}

This is the issue that we want to curb in our application. We don’t want IDs. We want to be able to interact within our application smoothly so users can see who is selling what.

We shall now use populate in Mongoose to help us with the problem: For a product, I want to populate the name and id of the farm associated with it:

Product.find()
.populate('farm', 'name')
.then(product=>console.log(product))
.catch(error=>console.log(error));

For a farm, I will populate the entire products documents associated with it:

Farm.find()
.populate('products')
.then(farm=>console.log(farm))
.catch(error=>console.log(error));

Now, we will check what our farm and products look like after using populate in Mongoose:

Product:

{
  _id: 6170854b496fcd1b541f5b1a,
  name: 'Whole Wheat Grains',
  price: 1,
  category: 'vegetable',
  farm: { _id: 6170847b496fcd1b541f5b19, name: "Giovanni's Wheat Fields" },
  __v: 0
}

Farm:

{
  products: [
    {
      _id: 6170854b496fcd1b541f5b1a,
      name: 'Whole Wheat Grains',
      price: 1,
      category: 'vegetable',
      farm: 6170847b496fcd1b541f5b19,
      __v: 0
    }
  ],
  _id: 6170847b496fcd1b541f5b19,
  name: "Giovanni's Wheat Fields",
  city: 'Marzamemi, Sicily',
  email: 'giovanniswheat@myfarms.com',
  __v: 1
}

We have successfully learned how to use populate in Mongoose.

See Also: Explaining the Ultimate Difference Between MongoDB vs Mongoose