Search code examples
node.jsmongodbexpressmongoose-populate

Populate from One Model to Another Using Mongoose/MongoDB in Node/Express Application


I am struggling to understand the populate method in Mongoose, while having trouble populating fields from one Mongoose model to another. The first model Schema is:

var MprnSchema = new mongoose.Schema({
    mprNo: {type: Number, unique: true, required: true},
    siteName: String,
    buildingNo: Number,
    streetAddress: String,
    secondAddress: String,
    townCity: String,
    postCode: String,
    supplier: String,
    siteContactName: String,
    siteContactNo: String,
});

module.exports = mongoose.model("Mprn", MprnSchema);

And another Schema is:

var FaultSchema = new mongoose.Schema({
    jobRef: Number,
    mprNo: Number,
    requestedDate: {type: Date, default: Date.now},
    attendedDate: {type: Date, default: null},
    siteDetails: {type: mongoose.Schema.Types.ObjectId, ref: 'Mprn'},
    faultIssue: String,
});

However, when I try to populate the 'siteDetails' with the contents of Mprn, I get [] when using thhe code below:

  Fault.find(reportQuery).populate('siteDetails', 'siteName 
postCode').exec((err, faultResults) => {
        if(err){
              req.flash("error", err.message);
              res.redirect("/");
        }

        console.log(faultResults);
        res.render("reportResults", { queryResults: faultResults });   

        });

The object passed to be rendered (queryResults) only contains the Fault data and NOT the 'siteDetails' that should be populated. I think the problem may be when I am using the Fault.Create() method in the first place, should I be saving a reference to the MPRN model at this point, so that the there is an Id to be referenced when populating?

My samples collections are:

Fault

  {
    "jobRef": 60000,
    "mprNo": 123456,
    "faultIssue": "Test"
  }

Mprn

 {
    "mprNo": 123456,
    "siteName": "Smithson Gates",
    "buildingNo": 76,
    "streetAddress": "Garden Place",
    "secondAddress": "Greater Manchester",
    "townCity": "Salford",
    "postCode": "M5 3AP",
    "supplier": "test",
    "siteContactName": "Mr B Jones",
    "siteContactNo": "0161 000 0000"
 }

Solution

  • Well you are using latest version of mongodb... So, You can try below $lookup aggregation... and the plus point of using this is you don't need to store _id of Mprn collection in the Fault... You can easily join both the collections with mprn number

    Fault.aggregate([
      { "$match": reportQuery },
      { "$lookup": {
        "from": Mprn.collection.name,
        "let": { "mprNo": "$mprNo" },
        "pipeline": [
          { "$match": { "$expr": { "$eq": [ "$mprNo", "$$mprNo" ] } } }
        ],
        "as": "siteDetails"
      }},
      { "$unwind": "$siteDetails" }
    ])