在Next.js 13中用MongoDB更新数组内指定对象的income字段
正确实现MongoDB数组元素更新的方案(Next.js 13环境)
现有MongoDB文档结构
{ _id: ObjectId("78391283"), name: "Colors company", shops: [ {shopID: ObjectId("123456a1cb"), income: 0}, {shopID: ObjectId("2a1cb67890"), income: 0}, {shopID: ObjectId("2a1cb010111"), income: 0}, ... ], }
需求
通过POST请求传入参数,匹配对应companyID的公司文档,找到其shops数组中指定shopID的对象,将该对象的income字段加上amountToAdd的数值:
{ companyID: "78391283", shopID: "123456a1cb", amountToAdd: 200, }
原代码的问题
你写的代码有几个关键错误:
- 查询条件匹配错误,应该定位公司的
_id(即传入的companyID),而非直接用shopID作为文档ID - 更新操作符使用错误,MongoDB的设置操作符是
$set,不是set;累加数值需用原子操作符$inc,不能直接用parsedBody.amountToAdd + income这种写法 - 未在查询条件中指定
shops.shopID,无法定位数组中对应的店铺元素,shops.$.income里的$占位符也无法生效
正确实现代码
在Next.js 13的API路由中(App Router/Pages Router通用),正确实现如下:
import mongoose from 'mongoose'; import Company from '@/models/Company'; // 替换为你的公司模型路径 export async function POST(request) { const parsedBody = await request.json(); // 转换为MongoDB所需的ObjectId类型 const companyId = new mongoose.Types.ObjectId(parsedBody.companyID); const shopId = new mongoose.Types.ObjectId(parsedBody.shopID); const amountToAdd = parsedBody.amountToAdd; try { // 执行更新操作 const updatedCompany = await Company.findOneAndUpdate( // 查询条件:匹配公司ID,且shops数组包含指定shopID的元素 { _id: companyId, "shops.shopID": shopId }, // 更新操作:用$inc原子累加对应店铺的income { $inc: { "shops.$.income": amountToAdd } }, // 选项:返回更新后的文档 { new: true } ); if (!updatedCompany) { return new Response(JSON.stringify({ message: '公司或店铺不存在' }), { status: 404 }); } return new Response(JSON.stringify(updatedCompany), { status: 200 }); } catch (error) { return new Response(JSON.stringify({ message: '更新失败', error: error.message }), { status: 500 }); } }
关键说明
- 查询条件:同时指定
_id: companyId和"shops.shopID": shopId,MongoDB会自动定位到数组中匹配的元素,$占位符代表该元素在数组中的位置 - $inc操作符:MongoDB的原子累加操作符,能保证并发场景下数值修改的正确性,比“查询-修改-保存”的流程更安全高效
- ObjectId转换:MongoDB的
_id和shopID都是ObjectId类型,必须把传入的字符串转换为对应类型才能匹配成功
内容的提问来源于stack exchange,提问作者Tarak He
相关产品推荐
相关产品推荐

