You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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返回验证错误“Path user is 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 11:23:10