MongoDb 未填充 - returns 空数组(无错误)

MongoDb Not populating - returns empy array (no error)

问题:

尝试填充用户对象产品:使用所有匹配的产品对象,但是 returns 空数组

在发布这个问题之前我做了以下事情:

我已阅读 mongoose 文档,尝试按照说明实施 - 无济于事

  1. MongoDB Combining Collections - Not Populating
  2. Mongoose populate returns empty array or list of ObjectIds
  3. Mongoose populate not populating an array and always returns an empty array
  4. 以及他也尝试过的所有 7 个链接

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

这是我的回购协议,需要更多详细信息: https://github.com/FlyingVespa/Capstone-BE/tree/main/src

用户架构:

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);

产品架构: 从“猫鼬”导入猫鼬;

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);

添加新产品:

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));
    }
  }
};

获取单个用户:

  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);
      }
    };

当前日志输出:

{
    "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": "rgunton0@soup.io",
            "store_services": [
                "Overhead Doors",
                "HVAC",
                "Temp Fencing, Decorative Fencing and Gates"
            ],
            "shipping": "false"
        },
        "_id": "62569c28dff1ca6175d48299",
        "role": "user",
        "email": "malgeo0@boston.com",
        "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"
    }
}

模块版本:

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

保存新产品时,必须将产品的 _id(返回)添加到用户的产品数组中。

像这样

const createdProduct = await newProduct.save();

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

勾选Saving refs in mongoose