MongoDB不存在对应条目时如何新建?基于Mongoose实现咨询
现有代码存在的问题
- 你使用的
Year.find()返回的是匹配结果的数组,哪怕没有匹配到任何文档,返回的也是空数组[],而空数组在JavaScript中布尔判断为true,所以你写的if(found)永远成立,不会走到新建条目的分支里。如果要做单条查询应该用findOne()而不是find()。 - 回调写法可读性较低,也不容易做异常全链路捕获,建议使用async/await语法处理异步逻辑。
- 没有对save操作的错误做捕获,容易出现静默失败的问题。
推荐最优方案:使用upsert原子操作
Mongoose内置的upsert功能完全适配你的需求,是数据库层面的原子操作,比先查再写的逻辑性能更高,还能避免并发请求下重复创建条目的问题,不需要自己手写查询判断逻辑:
// 用户录入2022年数据时直接执行即可 await Year.updateOne( { year: 2022 }, // 匹配条件 { $set: { // 这里直接放用户录入的需要更新的字段即可 "sheet1.f_jan_acc": 5, "sheet1.gi_jan_acc": 2, // 其余字段按需传入 } }, { upsert: true } // 开启upsert,匹配不到就自动插入新文档 )
如果你的场景需要拿到更新/插入后的完整文档,可以使用findOneAndUpdate:
const yearDoc = await Year.findOneAndUpdate( { year: 2022 }, { $set: {/* 要更新的字段 */} }, { upsert: true, new: true, // 返回更新后的新文档,默认返回更新前的旧文档 setDefaultsOnInsert: true // 插入新文档时自动应用schema中定义的默认值(如果有配置默认值的话) } )
如果你坚持要使用先查后写的逻辑,优化写法如下
try { // 单条查询用findOne const foundYear = await Year.findOne({ year: 2022 }) if (!foundYear) { // 不存在则新建 await Year.create({ year: 2022 }) } // 后续执行更新逻辑 } catch (err) { console.error('操作失败:', err) }
额外优化建议
给year字段加上唯一索引,避免出现同年份重复条目的问题,修改schema如下:
const yearSchema = new mongoose.Schema({ year: { type: Number, unique: true // 加唯一索引 }, sheet1: { f_jan_acc: Number, gi_jan_acc: Number, mi_jan_acc: Number, ni_jan_acc: Number, tot_jan_acc: Number, } })
加了唯一索引后,即使出现并发请求也不会插入重复的year文档,数据一致性更有保障。
内容的提问来源于stack exchange,提问作者Rajan
相关产品推荐
相关产品推荐

