Express+Mongoose创建订单时userId必填校验错误求助
POST请求创建订单时Mongoose报ValidationError: userId必填错误
使用Express+Mongoose开发API时,提交POST请求创建订单返回500错误,报错信息为ValidationError: userId: Path userId is required。请求体中已包含顶层的userId字段,但Mongoose无法识别该字段。尝试过提取req.body.order作为参数,此时请求能成功但无法存入userId,还得把Schema里的userId设为非必填,不符合需求。
请求体内容
{ "order": [ { "item": { "id": "p2", "title": "Scarf", "description": "Red Scarf", "price": 8 }, "quantity": 2, "totalItemCost": 16 } ], "userId": "659e15b29fcef318fc03bde8" }
创建订单控制器代码
export const createOrderController = async (req: express.Request, res: express.Response) => { try { const order = req.body; console.log('order is ' + JSON.stringify(order)) let createdOrder = await createOrder({ order }) return res.status(200).json(createdOrder).end(); } catch (error) { console.log('Error is ' + error) return res.sendStatus(500) } }
订单Schema与模型代码
const productSchema = new mongoose.Schema({ id: { type: String, required: true }, title: { type: String, required: true }, description: { type: String, required: true }, price: { type: Number, required: true }, }) const OrderItemSchema = new mongoose.Schema({ item: { type: productSchema, required: true }, quantity: { type: Number, required: true }, totalItemCost: { type: Number, required: true } }) const OrderSchema = new mongoose.Schema({ order: { type: [OrderItemSchema], required: true }, userId: { type: String, required: true } }) export const OrderModel = mongoose.model('order', OrderSchema); export const createOrder = (createdOrder: Record<string, any>) => new OrderModel(createdOrder).save().then((order) => order.toObject())
问题原因
你在调用createOrder函数时,把整个请求体包裹在了一个order属性里,导致Mongoose接收到的数据结构是{ order: { order: [...], userId: "xxx" } },顶层并没有userId字段,所以触发必填校验失败。
修复方案
直接传入req.body给createOrder函数即可,不需要额外包裹order属性:
export const createOrderController = async (req: express.Request, res: express.Response) => { try { const orderData = req.body; console.log('order data is ' + JSON.stringify(orderData)) let createdOrder = await createOrder(orderData) // 直接传递请求体 return res.status(200).json(createdOrder).end(); } catch (error) { console.log('Error is ' + error) return res.sendStatus(500) } }
如果不想修改控制器的变量命名,也可以通过展开运算符传递所有属性:
let createdOrder = await createOrder({ ...order // 展开req.body的所有字段 })
验证
修改后,Mongoose会接收到符合OrderSchema定义的数据结构:包含order数组和顶层userId字段,能正常通过必填校验并保存订单数据。
内容的提问来源于stack exchange,提问作者chucknor
相关产品推荐
相关产品推荐

