为什么 Virtual Populate 不适用于 Node js 和 mongoose?场景:产品和用户评论

问题描述

我有评论和产品模型。如果用户对特定产品(id)进行评论,那么它会存储在评论模型数据库中,但我不喜欢将用户评论存储在产品模型数据库中。所以,我在产品模型中使用了虚拟填充而不是子引用。使用虚拟属性后,如果我们使用产品 id 查看详细信息,我们可以以 json 格式查看用户评论,但未保存在数据库中。但问题是我的虚拟属性(在产品模型中)无法正常工作当我在该产品 id 中发送请求时,没有以 json 格式显示用户评论(存储在评论模型数据库中)。这里有什么问题?

用户对存储在数据库中的产品 (id) 的评论

enter image description here

发送该产品 ID 的请求,以使用虚拟属性查看 json 格式的用户评论(但未在 json 中找到评论

enter image description here

在产品模型中

const productSchema = new Schema({

    name: {
        type: String,required: true,trim: true,},slug: {
        type: String,unique: true,price: {
        type: String,quantity: {
        type: Number,description: {
        type: String,offer: {
        type: Number,discount: {
        type: Number,productPictures: [{
        img: {
            type: String,],mainCategory: {
        type: mongoose.Schema.Types.ObjectId,ref: "category",required: [true,"It is a required field"],sub1Category: {
        type: mongoose.Schema.Types.ObjectId,sub2Category: {
        type: mongoose.Schema.Types.ObjectId,createdBy: {
        type: mongoose.Schema.Types.ObjectId,ref: "admin",vendor: {
        type: mongoose.Schema.Types.ObjectId,ref: "vendor",createdAt: {
        type: String,default: moment().format("DD/MM/YYYY") + ";" + moment().format("hh:mm:ss"),updatedAt: {
        type: String,{
    toJson: { virtuals: true },toObject: { virtuals: true },}
);

    productSchema.virtual("reviews",{

ref: "review",foreignField: "product",localField: "_id",// justOne: true
}); 

const Product = mongoose.model("product",productSchema);                   
           module.exports = Product;

评论模型中

const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const moment = require("moment");



const reviewSchema = new Schema({

user: {
    type: mongoose.Schema.Types.ObjectId,ref: "user","Review must belong to user"],product: {
    type: mongoose.Schema.Types.ObjectId,ref: "product","Review must belong to the product"],review: {
    type: String,"Review cannot be empty"],rating: {
    type: Number,min: 1,max: 5,createdAt: {
    type: String,updateddAt: {
    type: String,{
toJson: { virtuals: true },});


// pre middleware and populating user and product(we can also do populate in getAllReview in controller)

reviewSchema.pre(/^find/,function(next) {
// ^find here is we use regex and can able to find,findOne ...etc
this.populate({
    path: "product",select: " _id name",}).populate({
    path: "user",select: " _id fullName",});
next()
});


const Review = mongoose.model("review",reviewSchema);

module.exports = Review;

在 Review.js 中

const Review = require("../../models/Review.Models")
exports.createReview = async(req,res) => {
const review = await Review.create(req.body)

return res.status(201).json({
    status: true,review
})
}


exports.getAllReviews = async(req,res) => {
try {
    const reviews = await Review.find()

    return res.status(200).json({
        status: true,totalReviews: reviews.length,reviews
    })
} catch (error) {
    return res.status(400).json({
        status: false,error
    })
}}

在 Product.js 中

const Product = require("../../models/Product.Models");
exports.getProductDetailsById = async(req,res) => {
try {
    const { productId } = req.params;

    // const { productId } = req.body;

    if (productId) {
        const products = await Product.findOne({ _id: productId })
            .populate('reviews')

        return res.status(200).json({
            status: true,products,});
    } else {
        console.log("error display");
        return res.status(400).json({
            status: false,error: "params required...",});
    }
} catch (error) {
    return res.status(400).json({
        status: false,error: error,});
}

解决方法

在 Product.js 中试试这个

 try {
if (productId) {
  const products = await Product.findOne({ _id: productId }).populate(
    "reviews"
  );


  console.log(products);
  if (products) {
    return res.status(200).json({
      status: true,message: "Products is listed",products,reviw: products.reviews,});

只需要添加响应发送

 return res.status(200).json({
      status: true,});