MongoDB findByIdAndUpdate更新后文档重复创建问题求助
问题描述
现有MongoDB文档结构如下:
{ _id: new ObjectId("62dead1c5bcb14c13ab82c42"), artistName: 'Artist 1', artistSpotifyId: '6ckI88Ggj8DPe0TNAAVkj', connectedGroupId: '62de84faa65ba6e0552c8ce4', connectedGroupName: 'Group 1', createdBy: 'username1', createdAt: '2022-07-27T11:47:56', __v: 0 }
客户端实现了编辑群组ID和名称的服务,代码如下:
const editArtistGroup = async (_id, connectedGroup) => { const content = { _id, connectedGroup } const response = await axios.put('http://localhost:3001/artists', content) return response }
服务器端接收参数后执行更新操作的代码:
router.put('/', async (req, res) => { const { _id, connectedGroup } = req.body const connectedGroupId = connectedGroup.split(',')[0] const connectedGroupName = connectedGroup.split(',')[1] const updatedArtist = await Artist.findByIdAndUpdate( { _id: _id }, { $set: { connectedGroupId: connectedGroupId, connectedGroupName: connectedGroupName, }, }, ) res.json(updatedArtist) })
执行后,目标ID(62dead1c5bcb14c13ab82c42)的文档成功更新,但同时意外创建了一个带新ObjectId的重复文档。相同代码在其他项目运行正常,请问重复文档的产生原因是什么?
原因分析及解决方法
重复文档出现的核心原因是**findByIdAndUpdate的upsert选项被开启**(可能是全局配置或模型配置默认设置了upsert: true,也可能是传入的_id格式不匹配导致查询未命中触发了默认upsert)。
具体场景拆解:
_id格式不匹配:如果Mongoose Schema中_id定义为ObjectId类型,但客户端传入的是字符串格式的_id,服务器端未做类型转换就直接用于查询,会导致查询条件匹配不到目标文档。此时若upsert为true,Mongoose会自动创建新文档。- 全局/模型默认
upsert: true:你的项目中可能在Mongoose全局配置或该Artist模型的配置里,默认开启了upsert选项,而另一个正常运行的项目没有这个配置。
解决步骤:
- 显式关闭
upsert:在findByIdAndUpdate中明确设置upsert: false,避免意外创建新文档,同时建议加上new: true返回更新后的文档(默认返回更新前的):
const updatedArtist = await Artist.findByIdAndUpdate( { _id: _id }, { $set: { connectedGroupId: connectedGroupId, connectedGroupName: connectedGroupName, }, }, { upsert: false, new: true } )
- 确保
_id类型正确:服务器端将传入的字符串_id转换为Mongoose的ObjectId类型后再查询:
const { ObjectId } = require('mongoose'); // ... const updatedArtist = await Artist.findByIdAndUpdate( { _id: new ObjectId(_id) }, { $set: { connectedGroupId: connectedGroupId, connectedGroupName: connectedGroupName, }, }, { upsert: false, new: true } )
- 检查配置:查看
Artist模型的定义和Mongoose全局配置,确认是否有默认设置upsert: true的地方,如有则修改为false。
内容的提问来源于stack exchange,提问作者smoothlikebutter
相关产品推荐
相关产品推荐

