MongoDB使用$merge写入带唯一索引集合触发E11000重复键错误如何解决
问题产生原因
$merge的whenMatched规则仅用于处理执行聚合前目标集合中已存在的匹配文档,不会对本次聚合管道输出的结果集做重复数据校验和合并。- 你的源集合
testcoll存在多个user_id相同的文档,经过$addFields处理后,输出的结果集里会有多条newcoll值相同的文档:- 第一条
newcoll=5的文档写入时,目标集合无匹配数据,插入成功 - 第二条
newcoll=5的文档紧随处理时,$merge不会判定为同批次重复的匹配场景,会直接尝试执行插入操作,触发目标集合newcoll字段的唯一索引约束,抛出E11000重复键错误。
- 第一条
解决方案
核心思路是在聚合管道进入$merge阶段前,先对结果集按newcoll字段去重,保证输出的每条数据newcoll值唯一。
推荐在$addFields和$merge阶段之间插入如下两个阶段,对重复的newcoll数据做去重处理(示例为保留第一条出现的重复数据,可按需调整为保留最新、合并内容等逻辑):
// 按newcoll分组,保留每组第一条数据 { $group: { _id: '$newcoll', firstDoc: { $first: '$$ROOT' } } }, // 将分组后的数据恢复为原始文档结构 { $replaceRoot: { newRoot: '$firstDoc' } }
修改后的完整聚合代码如下:
db.testcoll .aggregate([ { "$project": {"_id": 0 } }, { $addFields: { newcoll: '$user_id', created_at: new Date(), updated_at: new Date(), }, }, // 新增去重阶段 { $group: { _id: '$newcoll', firstDoc: { $first: '$$ROOT' } } }, { $replaceRoot: { newRoot: '$firstDoc' } }, { $merge: { into: 'outputcoll', on: "newcoll", whenMatched: "keepExisting", whenNotMatched: "insert" } } ], { allowDiskUse: true }) // 数据量较大时可开启磁盘使用,避免内存超限
如果重复数据需要做内容合并而非直接丢弃,可修改$group阶段的字段规则,自行实现聚合逻辑后再写入目标集合。
内容的提问来源于stack exchange,提问作者user13000875
相关产品推荐
相关产品推荐

