usr30911
usr30911

Reputation: 2781

express mongoose populate issue

I have 2 models and I'm trying to use the populate function to get a collated response.

My model is as follows

const mongoose = require('mongoose');

const RegisterEmpSchema = new mongoose.Schema({
    empID: Number,
    empName: String,
    empPhone: String,
    empProj: String
}, {
    timestamps: true
});

const RegisterEntriesSchema = new mongoose.Schema({
    registerType: String,
    registerItemsQuantity: Number,
    registerItemsDesc: String,
    empID: {
        type: mongoose.Schema.Types.Number,
        ref: 'registerEmpModel'
    }
}, {
    timestamps: true
});

RegisterEntriesSchema.index({ createdAt: 1 }, { expires: '525601m' });

const registerEmpModel = mongoose.model('RegisterEmpSchema', RegisterEmpSchema, 'registerEmployeeCollection');
const registerEntriesModel = mongoose.model('RegisterEntriesSchema', RegisterEntriesSchema, 'registerEntriesCollection');

module.exports = {
    registerEmpModel, registerEntriesModel,
}

When I try to fetch all entries from registerEntries it returns only the registerEntries and doesn't populate the response with registerEmp values

// Retrieve and return all registers from the database.
exports.findAllRegisterEntries = (req, res) => {

    registerEntriesModel.
        find().
        populate('RegisterEmpSchema').
        exec(function (err, data) {
            if (err) return console.log(err);
            res.send(data);
        });
};

My controller code where I save the model data https://pastebin.com/fj84azkM

Upvotes: 0

Views: 100

Answers (2)

Shihab
Shihab

Reputation: 2679

Here ref would be the collection name:

const RegisterEntriesSchema = new mongoose.Schema({
    registerType: String,
    registerItemsQuantity: Number,
    registerItemsDesc: String,
    empID: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'registerEmpModel' // Collection name
    }
}, {
    timestamps: true
});

And you have to populate the field not the model:

registerEntriesModel.
        find().
        populate('empID').
        exec(function (err, data) {
            if (err) return console.log(err);
            res.send(data);
        });

Upvotes: 1

SuleymanSah
SuleymanSah

Reputation: 17888

I think you cannot use populate in this scenario, because you are trying to populate on the empID field, but mongoose does not know that empID is the empID in employee model, by default it will try to match this empID on the _id field of the employee model.

One way to solve this is using _id field instead of empID field in the employee schema:

const RegisterEmpSchema = new mongoose.Schema(
  {
    _id: mongoose.Schema.Types.Number,
    empName: String,
    empPhone: String,
    empProj: String
  },
  {
    timestamps: true
  }
);

And creating employees using this sample body:

{
    "_id": 1,
    "empName": "emp 1 name",
    "empPhone":"emp 1 phone",
    "empProj": "emp 1 proj"
}

Now you can populate like this:

exports.findAllRegisterEntries = (req, res) => {

  registerEntriesModel
    .find()
    .populate("empID")   // note that here we use the fieldName
    .exec(function(err, data) {
      if (err) return console.log(err);
      res.send(data);
    });
};

Which will result like this:

[
    {
        "_id": "5dea4f795668341d0cb51a46",
        "registerType": "register type 1",
        "registerItemsQuantity": 1,
        "registerItemsDesc": "register desc",
        "empID": {
            "_id": 1,
            "empName": "emp 1 name",
            "empPhone": "emp 1 phone",
            "empProj": "emp 1 proj",
            "createdAt": "2019-12-06T12:54:06.446Z",
            "updatedAt": "2019-12-06T12:54:06.446Z",
            "__v": 0
        },
        "createdAt": "2019-12-06T12:54:17.986Z",
        "updatedAt": "2019-12-06T12:54:17.986Z",
        "__v": 0
    },
    {
        "_id": "5dea4f7b5668341d0cb51a47",
        "registerType": "register type 2",
        "registerItemsQuantity": 2,
        "registerItemsDesc": "register desc",
        "empID": {
            "_id": 2,
            "empName": "emp 2 name",
            "empPhone": "emp 2 phone",
            "empProj": "emp 2 proj",
            "createdAt": "2019-12-06T12:54:14.762Z",
            "updatedAt": "2019-12-06T12:54:14.762Z",
            "__v": 0
        },
        "createdAt": "2019-12-06T12:54:19.930Z",
        "updatedAt": "2019-12-06T12:54:19.930Z",
        "__v": 0
    }
]

As a second alternative, if you don't want to make any changes in your schemas, you can use aggregate like this:

router.get("/entry", async (req, res) => {
  const result = await registerEntriesModel.aggregate([
    {
      $lookup: {
        from: "registerEmployeeCollection",
        localField: "empID",
        foreignField: "empID",
        as: "employee"
      }
    },
    {
      $addFields: { employee: { $arrayElemAt: ["$employee", 0] } }
    }
  ]);

  res.send(result);
});

Which will give an output like this:

[
    {
        "_id": "5dea49170817b24bb8f37665",
        "registerType": "register type 1",
        "registerItemsQuantity": 1,
        "registerItemsDesc": "register desc",
        "empID": 1,
        "createdAt": "2019-12-06T12:27:03.841Z",
        "updatedAt": "2019-12-06T12:27:03.841Z",
        "__v": 0,
        "employee": {
            "_id": "5dea49020817b24bb8f37663",
            "empID": 1,
            "empName": "emp 1 name",
            "empPhone": "emp 1 phone",
            "empProj": "emp 1 proj",
            "createdAt": "2019-12-06T12:26:42.213Z",
            "updatedAt": "2019-12-06T12:26:42.213Z",
            "__v": 0
        }
    },
    {
        "_id": "5dea491e0817b24bb8f37666",
        "registerType": "register type 2",
        "registerItemsQuantity": 2,
        "registerItemsDesc": "register desc",
        "empID": 2,
        "createdAt": "2019-12-06T12:27:10.696Z",
        "updatedAt": "2019-12-06T12:27:10.696Z",
        "__v": 0,
        "employee": {
            "_id": "5dea490b0817b24bb8f37664",
            "empID": 2,
            "empName": "emp 2 name",
            "empPhone": "emp 2 phone",
            "empProj": "emp 2 proj",
            "createdAt": "2019-12-06T12:26:51.130Z",
            "updatedAt": "2019-12-06T12:26:51.130Z",
            "__v": 0
        }
    }
]

Upvotes: 1

Related Questions