NodeJS更新MongoDB文档报错:无法修改不可变字段_id
NodeJS更新MongoDB时
_id字段不可修改的问题解决 问题场景
我尝试用NodeJS更新MongoDB数据,代码如下:
Controller.js
updateProduct: async (req, res) => { try { const { params: { id } } = req; const { body } = req; if (!body || Object.keys(body).length === 0) { Response.ERROR(res, new createError.BadRequest()); } else { let product = await ProductsService.updateP(id, body); } if (!product) { Response.ERROR(res, new createError.NotFound()); } else { Response.SUCCSESS(res, 201, `Producto actualizado`, product); } } catch (error) { debug(error); Response.ERROR(res); } },
Services.js
const updateP = async (id, product) => { const collection = await Database(COLLECTION); return collection.updateOne({_id: new ObjectId(id)}, { $set: { ...product } }) };
数据库原始数据:
{ "_id": "651cd5d91e3c20bda7cea881", "name": "shoes", "price": 359, "quantity": 10 }
请求的body包含_id字段,执行更新时触发错误:
MongoServerError: Performing an update on the path '_id' would modify the immutable field '_id'
期望更新后的数据:
{ "_id": "651cd5d91e3c20bda7cea881", "name": "Coca-cola", "price": 359, "quantity": 10 }
错误原因
MongoDB的_id是文档的唯一标识,属于不可变字段,无法通过$set操作修改。当前代码直接把包含_id的请求body展开到$set中,因此触发报错。
另外,Controller代码存在作用域问题:let product在else块内声明,外部的if (!product)会访问到未定义的变量,导致即使更新成功,也会返回NotFound错误。
解决方案
- 剔除请求body中的
_id字段:更新前移除传入对象里的_id,避免尝试修改不可变字段。 - 修正Controller变量作用域:将
product变量声明移到else块外部,确保后续判断能正确访问更新结果。 - 改用
findOneAndUpdate:直接返回更新后的文档,无需额外查询,同时方便前端获取最新数据。
修改后的代码示例
修正后的Services.js
const { ObjectId } = require('mongodb'); const updateP = async (id, product) => { const collection = await Database(COLLECTION); // 解构剔除_id,生成仅含可更新字段的对象 const { _id, ...updateData } = product; // 执行更新并返回修改后的文档 return collection.findOneAndUpdate( { _id: new ObjectId(id) }, { $set: updateData }, { returnDocument: 'after' } ); };
修正后的Controller.js
updateProduct: async (req, res) => { try { const { params: { id } } = req; const { body } = req; let product; // 移至外部声明,确保作用域覆盖后续判断 if (!body || Object.keys(body).length === 0) { Response.ERROR(res, new createError.BadRequest()); } else { product = await ProductsService.updateP(id, body); } // 判断更新后的文档是否存在 if (!product?.value) { Response.ERROR(res, new createError.NotFound()); } else { Response.SUCCSESS(res, 201, `Producto actualizado`, product.value); } } catch (error) { debug(error); Response.ERROR(res); } },
内容的提问来源于stack exchange,提问作者fg daniel
相关产品推荐
相关产品推荐

