Search code examples
node.jsmongoose

Why I can't populate the data from organization?


I have 2 schemas.

organization Schema and inventory schema

Organization Schema was like this

const mongoose = require("mongoose");

const organizationSchema = new mongoose.Schema({
  organizationName: {
    type: String,
    required: true,
  },
});

organizationSchema.virtual("inventories", {
  ref: "Inventory",
  // Localfield is user id
  localField: "_id",
  // forefield is owner field in task
  foreignField: "owner",
});


organizationSchema.virtual("user", {
  ref: "User",
  localField: "_id",
  foreignField: "organizationId",
});

const Organization = mongoose.model("Organization", organizationSchema);

Inventory Schema was like this

const inventorySchema = new mongoose.Schema({
  inventoryName: {
    type: String,
    required: true,
  },
  owner: {
    type: mongoose.Schema.Types.ObjectId,
    required: true,
    ref: 'Organization'
  },
  users: [{ type: ObjectId, ref: "User" }],
});

inventorySchema.virtual("items", {
  ref: "Item",
  localField: "_id",
  foreignField: "inventoryId",
});

const Inventory = mongoose.model("Inventory", inventorySchema);

So in the api path. I wanna grab all the inventory related to certain organization. So i am populating like this. But I only get back the organization without populated data.

What am I doing wrong here?

router.get("/organizations/:orgId/inventory", auth, async (req, res) => {
  try {
    let organization = await Organization.findOne({
      _id: req.params.orgId,
    }).populate('user')
    res.send(organization)
  } catch (err) {
    return res.status(404).send({ error: "Organization not found" });
  }
});

API I am calling {{url}}/organizations/65ec63bee52ddf849fe70f76/inventory

enter image description here enter image description here


Solution

  • Firstly, your code is trying to populate user and not inventories so you need to change your code to:

    const organization = await Organization.findOne({
       _id: req.params.orgId,
    }).populate('inventories');
    

    Secondly, when you use the express res.send() method the argument passed to this method can be one of many different types such an String, Array, Object etc. Express will use the argument type to determine which Content-Type to set in the response header. In your case you are sending an object so express will set that to Content-Type: application/json.

    That's important to understand because mongoose virtuals are not included when the data is passed to toJSON() and toObject(). Since inventories is a virtual it won't be output in the data. You can fix that by setting the option in your schema:

    const organizationSchema = new mongoose.Schema({
       organizationName: {
          type: String,
          required: true,
       },
    },{
       toJSON: { virtuals: true },
       toObject: { virtuals: true }
    });