Using .populate() with mongoDB
Tags: mongodb, populate, database
Published: 2022-03-17 10:50:14

---
title: Using .populate() with mongoDB
published: true
description: When cross-referring the collections we can easily get the data from one to another with populate method
tags: MongoDB, populate, database
//cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gre2tn72y79tc7vmmxyk.jpg
---

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gre2tn72y79tc7vmmxyk.jpg)

Let's take a common example of eCommerce website with two collections for the products and the categories. 

Each product belongs to a certain category like "shoes", "hats", "pants" – and we want to refer to a corresponding collection from each product. 

We do not want to include the actual name of category into a product's record since it will complicate renaming categories – imagine we have thousands of shoes belonging to the "shoes" category and then we decide to rename it to "footwear". To do so we will need to update all the products to replace "shoes" to "footwear". 

Instead if we only refer to the "shoes" record from categories collection by it's id then we only need to update one record in the categories collection and rename it from "shoes" to "footwear". All the products pointing to this category will not be needed to get updated since the id of the category will not change. 

And when we fetch data for the products in the `category_id` field we have id of the category record from the categories collection. But what we want to get instead is the actual name of this category. This could be easily achieved with `.populate()` method. Let's see how.

The product schema:

```javascript
const mongoose = require("mongoose");

const productSchema = new mongoose.Schema({
  name: { type: String, required: true, unique: true },
  price: { type: Number, required: true },
  color: { type: String, required: true },
  description: { type: String, required: true },
  category_id: { type: mongoose.Types.ObjectId , required: true, unique: true, ref: 'categories' },
});

module.exports = mongoose.model("products", productSchema );
```

As we can see in the `category_id` we have id of the corresponding category from another collection, namely from "categories". 

The categories schema:

```javascript
const mongoose = require("mongoose");

const categorySchema = new mongoose.Schema({
  category: { type: String, required: true, unique: true },
});

module.exports = mongoose.model("categories", categorySchema);
```

Here we only have a name of the category. 

Now what you can do is to add `.populate()` method when you are getting products from the DB to say that instead of `category_id` shown as it is (the default mongoDB random sequence of letters and numbers) we want to fetch the corresponding category's name and use it instead. For example, we want to find all the products: 

```javascript
async findAll (req, res) {
    try {
        let product = await products.find({}).populate('category_id')
        res.send(product)
    }
    catch(e) {
        res.send({e})
    }
}
```

So now all the products will come with name of category included (instead of id reference).

Let's see the results in Postman. First, this is how it will be without `.populate()`. You can see that in the products data fetched we can only see id of the category, obviously we can't use it for rendering purposes:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yi1rcz32mnn5yg29986x.png)

Now same request but with `.populate()`. Now instead of id we can see the actual name of the category which we can render right away:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ejh8bxqmfibb339qgagc.png)

🤷‍♀️

#### Update: with nested cross-references we can also use `.populate()`. 

For example, we have products referring to the subcategories and those subcategories are referring to the categories. Then we will use nested `.populate()`:

```javascript
async findProducts(req, res){
        try{
            const products = await Products.find({}).populate({ 
             path: 'subcategoryId',
             populate: {
               path: 'categoryId',
               model: 'Categories'
           } 
       })
```