使用Mongoose的findOneAndUpdate时如何仅返回$push新增的数组元素
问题原因与前置修复点
当前写法存在两个问题:
- 直接用
$push传入数组会把整个数组作为单个内嵌文档插入,必须搭配$each操作符才能批量插入多条记录 findOneAndUpdate默认返回更新后的全量文档,所以会带上所有历史salesDate数据
解决方案1:直接构造返回结果(最推荐,性能最优)
你要插入的新记录本身在本地就有完整数据,只需要提前给每条记录生成mongoose默认的ObjectId,插入完成后直接返回这部分数据即可,不需要从数据库返回的全量数据中截取。该方案不受并发更新影响,不会出现截取到其他请求新增数据的问题,稳定性最高。
const { Types } = require('mongoose'); const salesObj = [{ name: "Doe" }, { name: "Tim" }]; // 提前给新增记录生成_id,和数据库自动生成的规则完全一致 const newSalesRecords = salesObj.map(item => ({ ...item, _id: new Types.ObjectId() })); // 执行更新 await Car.findOneAndUpdate( { _id: "6179bd464c68a217e895703c" }, { $push: { "salesInfo.salesDate": { $each: newSalesRecords } } }, { upsert: false, new: true } ); // 直接构造要求的返回格式 const response = { data: { salesInfo: { salesDate: newSalesRecords } } };
解决方案2:从更新返回的全量数据中截取
如果不想提前生成_id,也可以利用已知的本次插入条数,对返回的数组做截取:
const salesObj = [{ name: "Doe" }, { name: "Tim" }]; const insertCount = salesObj.length; const fullData = await Car.findOneAndUpdate( { _id: "6179bd464c68a217e895703c" }, { $push: { "salesInfo.salesDate": { $each: salesObj } } }, { upsert: false, new: true, fields: { _id: 0, "salesInfo.salesDate": 1 } } ); // 截取最后insertCount条,就是本次新增的记录 const response = { data: { salesInfo: { salesDate: fullData.salesInfo.salesDate.slice(-insertCount) } } };
内容的提问来源于stack exchange,提问作者Ven Nilson
相关产品推荐
相关产品推荐

