Home > other >  MongoDb Not populating - returns empy array (no error)
MongoDb Not populating - returns empy array (no error)

Time:04-14

Problem:

Trying to populate the User object products: with all matching Products Object, but returns empty array

Before posting this question I did the following:

I have read the mongoose Docs, tried implementing as stated - to no avail

  1. mongodb populate method not working
  2. MongoDB Combining Collections - Not Populating
  3. Mongoose populate() returns empty array with no errors
  4. Mongoose populate returns empty array or list of ObjectIds
  5. Mongoose populate not populating an array and always returns an empty array
  6. Mongoose returning empty array after populate() method and all 7 links he tried aswell

The following in all possible combinations : -async -exec() -then() -populate() with/without specifying path, model, select

here is my repo incase more details are needed: https://github.com/FlyingVespa/Capstone-BE/tree/main/src

User Schema:

const userSchema = new Schema(
      {
        role: notReqString,
        email: {
          type: String,
          lowercase: true,
          required: [true, "An email is required."],
          unique: [true, "An email is already registered."],
          match: [/. \@. \.. /, "Not a valid email"],
          // validate: [isEmail, "Please enter valid email"],
        },
        password: reqString,
        url: notReqString,
        businessname: reqString,
        category: notReqString,
        username: notReqString,
        address: {
          lat: notReqString,
          lng: notReqString,
          street_number: notReqString,
          street_name: notReqString,
          city: notReqString,
          state: notReqString,
          country: notReqString,
        },
        companydetails: {
          bio: notReqString,
          mobile: notReqString,
          public_email: notReqString,
          store_services: { type: Array },
          shipping: notReqString,
        },
        tradingtimes: [
          {
            day: notReqString,
            trading: reqBoolean,
            open: notReqString,
            closed: notReqString,
          },
          {
            day: notReqString,
            trading: reqBoolean,
            open: notReqString,
            closed: notReqString,
          },
          {
            day: notReqString,
            trading: reqBoolean,
            open: notReqString,
            closed: notReqString,
          },
          {
            day: notReqString,
            trading: reqBoolean,
            open: notReqString,
            closed: notReqString,
          },
          {
            day: notReqString,
            trading: reqBoolean,
            open: notReqString,
            closed: notReqString,
          },
          {
            day: notReqString,
            trading: reqBoolean,
            open: notReqString,
            closed: notReqString,
          },
          {
            day: notReqString,
            trading: reqBoolean,
            open: notReqString,
            closed: notReqString,
          },
        ],
    
        img_logo: {
          ...notReqString,
          default: () => {
            return `https://eu.ui-avatars.com/api/?name=Test`;
          },
        },
    
        products: [{ type: Schema.Types.ObjectId, ref: "Product" }], /*REFRENCING HERE*/
      },
      { timestamps: true }
    );

userSchema.pre("save", async function (next) {
  const newUser = this;
  const plainPW = newUser.password;
  if (newUser.isModified("password")) {
    newUser.password = await bcrypt.hash(plainPW, 10);
  }
  next();
});

userSchema.methods.toJSON = function () {
  const userDocument = this;
  const userObject = userDocument.toObject();
  delete userObject.password;
  delete userObject.__v;
  delete userObject.refreshToken;
  return userObject;
};

export default model("User", userSchema);

Product Schema: import mongoose from "mongoose";

const { Schema, model } = mongoose;
const reqString = { type: String, required: false };
const notReqString = { type: String, required: false };
const reqNumber = { type: Number, required: true };
const productSchema = new Schema(
  {
    businessId: {
      type: Schema.Types.ObjectId,
      ref: "User",
      required: true,
    },
    name: notReqString,
    price: reqNumber,
    units: notReqString,
    status: notReqString,
    sku: notReqString,
    brand: notReqString,
    description: notReqString,

    image: {
      ...notReqString,
      default: () => {
        return `https://eu.ui-avatars.com/api/?name=product`;
      },
    },
  },
  { timestamps: true }
);

productSchema.methods.toJSON = function () {
  const productDocument = this;
  const productObject = productDocument.toObject();
  delete productObject.__v;
  return productObject;
};

export default model("Product", productSchema);

Add new product:

export const addNewProduct = async (req, res, next) => {
  try {
    const userId = req.params.userId;
    console.log(req.params);
    const user = await User.findById(userId);
    if (!user) {
      return next(createError(404, `User with id ${userId} not found`));
    }
    const newProductData = { ...req.body, businessId: userId };
    const newProduct = new Product(newProductData);
    const createdProduct = await newProduct.save();

    res.status(201).send(createdProduct);
  } catch (error) {
    if (error.name === "ValidationError") {
      next(createError(400, error));
    } else {
      next(createError(500, error));
    }
  }
};

Fetch Single User:

  export const getSingleUser = async (req, res, next) => {
      try {
        const userId = req.params.userId;
        User.findById(userId)
          .populate({ path: "products", model: "Product" })
          .exec((err, result) => {
            if (err) {
              console.log("err", err);
              return res.send({ error: err });
            }
            console.log("result", result);
            res.send({ result: result });
          });
      } catch (error) {
        next(error);
      }
    };

current log output:

{
    "result": {
        "address": {
            "lat": "38.2305534",
            "lng": "15.5532993",
            "street_number": "1256",
            "street_name": "Autumn Leaf",
            "city": "Messina",
            "state": "Sicilia",
            "country": "Italy"
        },
        "companydetails": {
            "bio": "i vel nisl. Duis ac nibh. Fusce lacus purus, aliquet at",
            "mobile": "139-432-2309",
            "public_email": "[email protected]",
            "store_services": [
                "Overhead Doors",
                "HVAC",
                "Temp Fencing, Decorative Fencing and Gates"
            ],
            "shipping": "false"
        },
        "_id": "62569c28dff1ca6175d48299",
        "role": "user",
        "email": "[email protected]",
        "url": "Orca",
        "businessname": "Kaymbo",
        "category": "Capital Goods",
        "username": "llefort0",
        "tradingtimes": [
            {
                "day": "0",
                "trading": true,
                "_id": "62569c28dff1ca6175d4829a"
            },
            {
                "day": "1",
                "trading": false,
                "_id": "62569c28dff1ca6175d4829b"
            },
            {
                "day": "2",
                "trading": true,
                "_id": "62569c28dff1ca6175d4829c"
            },
            {
                "day": "3",
                "trading": true,
                "_id": "62569c28dff1ca6175d4829d"
            },
            {
                "day": "4",
                "trading": false,
                "_id": "62569c28dff1ca6175d4829e"
            },
            {
                "day": "5",
                "trading": false,
                "_id": "62569c28dff1ca6175d4829f"
            },
            {
                "day": "6",
                "trading": false,
                "_id": "62569c28dff1ca6175d482a0"
            }
        ],
        "products": [],
        "img_logo": "https://eu.ui-avatars.com/api/?name=Test",
        "createdAt": "2022-04-13T09:47:20.541Z",
        "updatedAt": "2022-04-13T09:47:20.541Z"
    }
}

modules versions:

  "node": v14.17.5 
  "express":"^4.17.1", 
  "mongodb": "^4.1.3",
  "mongoose": "^6.2.10"

CodePudding user response:

When you save the new product, you have to add the product's _id (which is returned) to the user's product's array.

Something like this

const createdProduct = await newProduct.save();

// Since you have access to user you can do
user.products.push(createdProduct._id);
await user.save();

Check Saving refs in mongoose

  • Related