为啥 Virtual Populate 不能在 Node js 和 mongoose 上运行?场景:产品和用户评论
Posted
技术标签:
【中文标题】为啥 Virtual Populate 不能在 Node js 和 mongoose 上运行?场景:产品和用户评论【英文标题】:why Virtual Populate not working on Node js and mongoose? Scenario : Product and Review by user为什么 Virtual Populate 不能在 Node js 和 mongoose 上运行?场景:产品和用户评论 【发布时间】:2021-08-13 11:29:30 【问题描述】:我有评论和产品模型。如果用户对特定产品(id)进行评论,那么它将存储在评论模型数据库中,但我不喜欢将用户评论存储在产品模型数据库中。所以,我在产品模型中使用了虚拟填充而不是子引用。使用虚拟属性后,如果我们使用产品ID查看详细信息,我们可以看到json格式的用户评论但未保存在数据库中。但问题是我的虚拟属性(在产品模型中)无法正常工作当我在该产品 id 中发送请求时,不以 json 格式显示用户的评论,该产品 id 已经被用户评论(存储在评论模型数据库中)。这里有什么问题?
用户对存储在数据库中的产品 (id) 的评论
使用虚拟属性发送该产品 ID 的请求以查看 json 格式的用户评论(但在 json 中未找到评论)
在产品模型中
const productSchema = new Schema(
name:
type: String,
required: true,
trim: true,
,
slug:
type: String,
required: true,
unique: true,
,
price:
type: String,
required: true,
,
quantity:
type: Number,
required: true,
,
description:
type: String,
required: true,
trim: true,
,
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,
ref: "category",
required: [true, "It is a required field"],
,
sub2Category:
type: mongoose.Schema.Types.ObjectId,
ref: "category",
required: [true, "It is a required field"],
,
createdBy:
type: mongoose.Schema.Types.ObjectId,
ref: "admin",
required: true,
,
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,
default: moment().format("DD/MM/YYYY") + ";" + moment().format("hh:mm:ss"),
,
,
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",
required: [true, "Review must belong to user"],
,
product:
type: mongoose.Schema.Types.ObjectId,
ref: "product",
required: [true, "Review must belong to the product"],
,
review:
type: String,
required: [true, "Review cannot be empty"],
,
rating:
type: Number,
min: 1,
max: 5,
,
createdAt:
type: String,
default: moment().format("DD/MM/YYYY") + ";" + moment().format("hh:mm:ss"),
,
updateddAt:
type: String,
default: moment().format("DD/MM/YYYY") + ";" + moment().format("hh:mm:ss"),
,
,
toJson: virtuals: true ,
toObject: 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,
);
【问题讨论】:
在您的架构中,将toJson: virtuals: true
中的json 部分大写-即toJSON: virtuals: true
它没有对此产生任何影响,下面的评论已经解决了我的问题。无论如何,谢谢你伸出援手
当我测试它时它工作得很好......但没关系,因为你似乎已经解决了这个问题。
【参考方案1】:
在 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,
message: "Products is listed",
products,
reviw: products.reviews,
);
【讨论】:
谢谢,真的成功了。另外,我忘记从产品模型中删除 justOne: true 因为这只会显示一条评论。以上是关于为啥 Virtual Populate 不能在 Node js 和 mongoose 上运行?场景:产品和用户评论的主要内容,如果未能解决你的问题,请参考以下文章