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

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)。

具体场景拆解:

  1. _id格式不匹配:如果Mongoose Schema中_id定义为ObjectId类型,但客户端传入的是字符串格式的_id,服务器端未做类型转换就直接用于查询,会导致查询条件匹配不到目标文档。此时若upsert为true,Mongoose会自动创建新文档。
  2. 全局/模型默认upsert: true:你的项目中可能在Mongoose全局配置或该Artist模型的配置里,默认开启了upsert选项,而另一个正常运行的项目没有这个配置。

解决步骤:

  1. 显式关闭upsert:在findByIdAndUpdate中明确设置upsert: false,避免意外创建新文档,同时建议加上new: true返回更新后的文档(默认返回更新前的):
const updatedArtist = await Artist.findByIdAndUpdate(
  { _id: _id },
  {
    $set: {
      connectedGroupId: connectedGroupId,
      connectedGroupName: connectedGroupName,
    },
  },
  { upsert: false, new: true }
)
  1. 确保_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 }
)
  1. 检查配置:查看Artist模型的定义和Mongoose全局配置,确认是否有默认设置upsert: true的地方,如有则修改为false。

内容的提问来源于stack exchange,提问作者smoothlikebutter

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 05:15:46