Mongoose重复保存文档疑问:首次导入RSS作者重复存储,二次导入正常
问题原因分析
这大概率是**异步并行操作引发的竞态条件(Race Condition)**导致的,我来给你拆解清楚:
- 首次处理feed时,你应该是并行处理多条条目(比如用了
forEach搭配异步函数、Promise.all这类方式)。每条条目都会触发「检查作者是否存在」的查询,而此时数据库里完全没有该作者的记录——几乎同时发起的多个findOne查询都会返回null,紧接着每个查询的后续逻辑都会执行「创建新作者」的操作。等这些异步的创建操作陆续完成,数据库里就多出了好几个重复的作者。 - 第二次处理同一份feed时,数据库里已经有了该作者的完整记录。不管你是并行还是串行处理条目,每个「检查作者是否存在」的查询都能精准命中已有文档,自然就不会重复执行创建逻辑了。
解决方案建议
要从根本上解决这个问题,推荐两种方案:
1. 数据库层面加唯一索引兜底
给作者模型的唯一标识字段(比如name、email这类不会重复的字段)添加唯一索引,这样即使代码层面的检查没拦住,MongoDB也会直接拒绝重复插入的请求,避免脏数据。
示例代码(Mongoose Schema):
const authorSchema = new mongoose.Schema({ name: { type: String, unique: true, // 唯一索引 required: true }, // 其他字段... });
2. 原子化操作避免竞态
改用Mongoose的findOneAndUpdate方法,配合upsert: true参数,原子性地完成「查找-不存在则创建」的操作——这个操作是MongoDB层面的原子操作,不会出现多个请求同时创建重复数据的情况。
示例代码:
// 替代原来的findOne + create逻辑 const author = await Author.findOneAndUpdate( { name: targetAuthorName }, // 匹配条件:作者名称 { name: targetAuthorName }, // 要插入/更新的字段 { upsert: true, new: true } // upsert=true:不存在则创建;new=true:返回最新的文档 );
内容的提问来源于stack exchange,提问作者user465001
相关产品推荐
相关产品推荐

