MongoDB执行findOneAndUpdate时如何判断指定字段是否被更新?
解决方案
方案1:返回更新前文档手动比对(最常用,无额外开销)
你可以在调用findOneAndUpdate时指定返回更新前的原文档,拿到后直接比对新旧quantity值即可判断是否发生变更,不需要额外事务,性能损耗几乎可忽略。
实现代码:
const newQuantity = 13; const lastReportedAt = new Date(); const oldDoc = db.collection("items").findOneAndUpdate( { "item": "box" }, { $set: { "quantity": newQuantity, "lastReportedAt": lastReportedAt } }, { upsert: true, returnOriginal: true // 配置返回更新前的旧文档,MongoDB NodeJS驱动3.x以上默认就是true,显式写更稳妥 } ).value; // 不同驱动版本取返回值的属性可能略有差异,部分版本用`returnedDocument` let isQuantityChanged = false; if (!oldDoc) { // 属于upsert新插入文档,quantity为首次设置,判定为变更 isQuantityChanged = true; } else { // 比对新旧quantity值 isQuantityChanged = oldDoc.quantity !== newQuantity; } // 触发通知逻辑 if (isQuantityChanged) { // 执行你的通知触发代码 }
方案2:拆分更新操作(适合不需要每次强制更新lastReportedAt的场景)
如果你的业务允许仅在quantity变更时才更新lastReportedAt,可以把quantity不等的条件加到查询语句里,此时返回的修改计数就直接对应quantity是否变更:
const newQuantity = 13; const lastReportedAt = new Date(); const updateResult = db.collection("items").updateOne( { "item": "box", "quantity": { $ne: newQuantity } // 仅当quantity和新值不等时才匹配执行更新 }, { $set: { "quantity": newQuantity, "lastReportedAt": lastReportedAt } }, { upsert: true } ); // matchedCount为1说明有文档匹配更新,upsertedCount为1说明是新插入,两种情况都代表quantity发生变更 const isQuantityChanged = updateResult.matchedCount > 0 || updateResult.upsertedCount > 0;
注意这个方案的限制是:如果quantity没有变化,lastReportedAt不会更新,需要根据你的业务需求选择。
内容的提问来源于stack exchange,提问作者ssssssleeeeee
相关产品推荐
相关产品推荐

