You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB条件式插入/替换文档:仅旧文档价格更低时更新

解决MongoDB Upsert时的重复键错误问题

错误原因

你遇到的E11000 duplicate key error,根源在于用replaceOne搭配upsert: true且filter包含price: {$lt: item.price}的逻辑:

  • 当集合中已存在_id匹配但price不小于当前条目值的文档时,filter无法命中任何结果;
  • 此时upsert会尝试插入当前条目作为新文档,而_id已存在,触发唯一键冲突。

解决方案

改用updateOne替代replaceOne,通过条件更新控制仅在现有文档price低于新值时执行更新,同时保留upsert实现插入逻辑。

方案1(MongoDB 4.2+推荐)

利用updateOne的condition参数直接判断更新条件:

await abc.bulkWrite(input.map(function (item) {
    return {
        updateOne: {
            filter: { _id: item._id },
            update: {
                $set: {
                    title: item.title,
                    price: item.price,
                    updated_at: item.updated_at
                }
            },
            upsert: true,
            // 仅当现有文档price小于新price时才执行更新
            condition: { $lt: ["$price", item.price] }
        }
    };
}));

方案2(兼容低版本MongoDB)

用$cond在更新逻辑中判断是否替换字段:

await abc.bulkWrite(input.map(function (item) {
    return {
        updateOne: {
            filter: { _id: item._id },
            update: {
                $set: {
                    updated_at: item.updated_at,
                    title: {
                        $cond: {
                            if: { $lt: ["$price", item.price] },
                            then: item.title,
                            else: "$title"
                        }
                    },
                    price: {
                        $cond: {
                            if: { $lt: ["$price", item.price] },
                            then: item.price,
                            else: "$price"
                        }
                    }
                }
            },
            upsert: true
        }
    };
}));

方案3(简化版,仅关注price更新)

如果只需要保证price取最大值,同时同步更新其他字段(无论price是否变化),可以用$max简化:

await abc.bulkWrite(input.map(function (item) {
    return {
        updateOne: {
            filter: { _id: item._id },
            update: {
                $max: { price: item.price },
                $set: {
                    updated_at: item.updated_at,
                    title: item.title
                }
            },
            upsert: true
        }
    };
}));

效果说明

  • 当文档不存在时:upsert触发插入,创建新文档;
  • 当文档存在且price低于新值时:执行更新,替换为新的字段值;
  • 当文档存在且price不低于新值时:不执行任何操作,避免无效更新和键冲突。

内容的提问来源于stack exchange,提问作者vbarbarosh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 00:04:57