MERN电商项目新增产品时user字段必填错误排查
MERN电商系统新增产品接口验证错误问题
问题说明
在Udemy平台Ghulam Abbas的《MERN Stack Full Ecommerce Site - Using React, Redux, Node.js》课程开发电商系统时,新增产品接口出现以下问题:
- 已将
req.user._id合并到req.body生成product对象,日志打印显示user字段存在 - 调用
Product.create(req.body)时,MongoDB返回验证错误“Pathuseris required”,产品无法存入数据库
相关代码片段
路由代码
router.route('/admin/newproducts').post(isUserAuthenticated, authroziedRole('admin'), newProducts);
产品控制器(newProducts方法)
const newProducts = asyncHandler(async (req, res) => { const product = { ...req.body, user: req.user._id }; console.log('new product', JSON.stringify(product, null, 2)) product = await Product.create(req.body); return res.status(200).json({ product, }); });
认证中间件(auth.js)
const AsyncHandler = require("express-async-handler"); const ErrorHandler = require("../utils/errorHandler"); const jwt = require("jsonwebtoken"); const User = require("../models/users"); // 验证用户是否已登录 const isUserAuthenticated = AsyncHandler(async (req, res, next) => { const { token } = req.cookies; console.log(token); if (!token) { return next(new ErrorHandler("Login First To view this content", 401)); } const decoded = jwt.verify(token, process.env.JWT_SCERET); req.user = await User.findById(decoded.id); next(); }); // 验证用户角色权限 const authroziedRole = (...roles) => { return (req, res, next) => { if (!roles.includes(req.user.role)) { return next( new ErrorHandler( `${req.user.role} is not allowed to access this resource` ) ); } next(); }; }; module.exports = { isUserAuthenticated, authroziedRole };
产品数据库模型
const mongoose = require("mongoose"); const productSchema = mongoose.Schema( { name: { type: String, required: [true, "Please Enter Product Name"], maxLength: [200, "Product Name cannot exceed 200 characters"], }, price: { type: Number, required: [true, "Please Enter Product Price"], maxLength: [5, "Product Price cannot exceed 5 characters"], }, description: { type: String, required: [true, "Please Enter Product Description"], maxLength: [3200, "Product Description cannot exceed 200 characters"], }, ratings: { type: Number, default: 0, }, images: [ { public_id: [ { type: String, required: true, }, ], url: [ { type: String, required: true, }, ], }, ], category: { type: String, required: [true, "Please Enter Product Category"], enum: { values: [ "Electronics", "Cameras", "Laptops", "Accessories", "Headphones", "Food", "Books", "Sports", "Outdoor", "Home", ], message: "Please select correct category", }, }, seller: { type: String, required: [true, "Please Enter Product Seller"], }, stock: { type: Number, required: [true, "Please Enter Product Stocks"], }, numOfReviews: { type: Number, default: 0, }, reviews: [ { user: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true, }, ratings: { type: Number, required: true, }, comment: { type: String, required: true, }, }, ], user: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true, }, }, { timestamps: true } ); const Product = mongoose.model('Product', productSchema); module.exports = Product;
API测试用JSON
[ { "name": "2 Ultra 128GB SDXC UHS-I Memory Card up to 80MB/s", "price": 45.89, "description": "Ultra-fast cards (2) to take better pictures and Full HD videos (1) with your compact to mid-range point-and-shoot", "ratings": 4.5, "images": [ { "public_id": "shopit/demo/nkkjkta63uiazppzkmjf", "url": "http://res.cloudinary.com/udemy-courses/image/upload/v1698577488/shopit/demo/nkkjkta63uiazppzkmjf.jpg" }, { "public_id": "shopit/demo/hz1iwdqzrvxtfxincvju", "url": "http://res.cloudinary.com/udemy-courses/image/upload/v1698577488/shopit/demo/hz1iwdqzrvxtfxincvju.jpg" }, { "public_id": "shopit/demo/oc2dvvkxyxukc13y9pjv", "url": "http://res.cloudinary.com/udemy-courses/image/upload/v1698577488/shopit/demo/oc2dvvkxyxukc13y9pjv.jpg" } ], "category": "Electronics", "seller": "Amazon", "stock": 50, "noOfReviews": 32, "reviews": [] } ]
错误信息
{ "message": "Path `user` is required.", "error": { "errors": { "user": { "name": "ValidatorError", "message": "Path `user` is required.", "properties": { "message": "Path `user` is required.", "type": "required", "path": "user" }, "kind": "required", "path": "user" } }, "_message": "Product validation failed", "name": "ValidationError", "message": "Product validation failed: user: Path `user` is required." }, "stack": "ValidationError: Product validation failed: user: Path `user` is required.\n at Document.invalidate (D:\\UrbanHub\\node_modules\\mongoose\\lib\\document.js:3187:32)\n at D:\\UrbanHub\\node_modules\\mongoose\\lib\\document.js:2980:17\n at D:\\UrbanHub\\node_modules\\mongoose\\lib\\schemaType.js:1368:9\n at process.processTicksAndRejections (node:internal/process/task_queues:77:11)" }
打印的合并后product对象
new product { "0": { "name": "2 Ultra 128GB SDXC UHS-I Memory Card up to 80MB/s", "price": 45.89, "description": "Ultra-fast cards (2) to take better pictures and Full HD videos (1) with your compact to mid-range point-and-shoot", "ratings": 4.5, "images": [ { "public_id": "shopit/demo/nkkjkta63uiazppzkmjf", "url": "http://res.cloudinary.com/udemy-courses/image/upload/v1698577488/shopit/demo/nkkjkta63uiazppzkmjf.jpg" }, { "public_id": "shopit/demo/hz1iwdqzrvxtfxincvju", "url": "http://res.cloudinary.com/udemy-courses/image/upload/v1698577488/shopit/demo/hz1iwdqzrvxtfxincvju.jpg" }, { "public_id": "shopit/demo/oc2dvvkxyxukc13y9pjv", "url": "http://res.cloudinary.com/udemy-courses/image/upload/v1698577488/shopit/demo/oc2dvvkxyxukc13y9pjv.jpg" } ], "category": "Electronics", "seller": "Amazon", "stock": 50, "noOfReviews": 32, "reviews": [] }, "user": "65aeb82fcdf62bb6e528fb84" }
问题根源及解决方案
问题1:控制器未使用合并后的对象创建产品
控制器代码中,你创建了合并user字段的product对象,但调用Product.create时传入的是原始req.body,而非合并后的对象。此外,用const声明的变量无法重新赋值,这也是代码中的隐性问题。
修正后的控制器代码:
const newProducts = asyncHandler(async (req, res) => { // 处理测试数据是数组的情况:如果req.body是数组,取第一个元素;否则直接用req.body const productBase = Array.isArray(req.body) ? req.body[0] : req.body; const productData = { ...productBase, user: req.user._id }; console.log('new product', JSON.stringify(productData, null, 2)) const product = await Product.create(productData); return res.status(200).json({ product, }); });
问题2:测试用JSON是数组格式
从打印的product对象可以看出,req.body是数组,合并user后生成的对象中,产品数据被放在了"0"键下,而mongoose的Product模型期望产品字段(name、price等)和user字段都在顶层对象中,导致模型验证时无法识别正确的结构。
修正后的测试用JSON:
{ "name": "2 Ultra 128GB SDXC UHS-I Memory Card up to 80MB/s", "price": 45.89, "description": "Ultra-fast cards (2) to take better pictures and Full HD videos (1) with your compact to mid-range point-and-shoot", "ratings": 4.5, "images": [ { "public_id": "shopit/demo/nkkjkta63uiazppzkmjf", "url": "http://res.cloudinary.com/udemy-courses/image/upload/v1698577488/shopit/demo/nkkjkta63uiazppzkmjf.jpg" }, { "public_id": "shopit/demo/hz1iwdqzrvxtfxincvju", "url": "http://res.cloudinary.com/udemy-courses/image/upload/v1698577488/shopit/demo/hz1iwdqzrvxtfxincvju.jpg" }, { "public_id": "shopit/demo/oc2dvvkxyxukc13y9pjv", "url": "http://res.cloudinary.com/udemy-courses/image/upload/v1698577488/shopit/demo/oc2dvvkxyxukc13y9pjv.jpg" } ], "category": "Electronics", "seller": "Amazon", "stock": 50, "noOfReviews": 32, "reviews": [] }
额外注意
- 确保
req.user已被正确赋值:可添加console.log(req.user)确认用户信息是否正常获取 - 检查模型中的
user字段类型是否与req.user._id匹配:两者都是ObjectId类型,无需额外转换
内容的提问来源于stack exchange,提问作者Rahul Jha
相关产品推荐
相关产品推荐

