0

0

MongoDB怎么实现数据的有则更新无则插入_upsert底层执行逻辑

P粉602998670

P粉602998670

发布时间:2026-03-18 09:52:03

|

818人浏览过

|

来源于php中文网

原创

upsert通过filter查询是否至少匹配一个文档来判断“有”或“无”,匹配则更新、否则插入;filter必须稳定唯一,推荐始终用$set避免覆盖,_id需谨慎处理以防重复或报错。

mongodb怎么实现数据的有则更新无则插入_upsert底层执行逻辑

upsert 是怎么判断“有”还是“无”的

本质就一条:MongoDB 用 filter 参数里的查询条件去查集合,只要找到**至少一个匹配文档**,就走更新(update);否则走插入(insert)。它不看字段值是否“真正变化”,也不管你 update 操作里改了啥,只认 filter 是否命中。

常见错误现象:upsert: true 却反复插入新文档——大概率是 filter 写成了动态值(比如带 Date.now() 或随机数),导致每次条件都不一样,永远查不到。

  • 使用场景:用户资料初始化、计数器初始化、配置项兜底写入
  • 关键点:filter 必须是稳定、可复现的唯一标识,比如 { userId: "u123" },而不是 { createdAt: { $gt: new Date() } }
  • 性能影响:如果 filter 字段没建索引,每次 upsert 都会全表扫描,写入延迟飙升

update 参数里写 $set 还是直接写字段值

取决于你是否想保留原文档其他字段。MongoDB 的 updateOne(含 upsert)默认是「替换式更新」,但加了 $set 就变成「局部更新」。

示例对比:

db.users.updateOne(
  { userId: "u123" },
  { name: "Alice", age: 30 }, // ❌ 无 $set:upsert 时插入完整文档,但更新时会删掉原 doc 其他字段(如 email)
  { upsert: true }
)
db.users.updateOne(
  { userId: "u123" },
  { $set: { name: "Alice", age: 30 } }, // ✅ 有 $set:无论插入还是更新,都只动指定字段
  { upsert: true }
)
  • 推荐始终用 $set,避免意外覆盖
  • 如果真要替换整个文档(比如 schema 重构),用 replaceOne 更明确,别靠 updateOne 的无操作符行为
  • 注意:$set 在 upsert 插入阶段等价于直接赋值,不影响行为,但语义更安全

为什么 _id 字段在 upsert 中特别容易出错

_id 是 MongoDB 的硬性约束字段,upsert 时如果 filter 不含 _id,而 update 操作又试图写入 _id,就会报错:Performing an insert operation on a collection with a field named _id

Ai好记
Ai好记

强大的AI音视频转录与总结工具

下载

根本原因:upsert 插入分支会尝试把 update 部分的字段直接当新文档内容,若含 _id,就等于手动指定 _id —— 这要求你确保该 _id 绝对不重复,且类型合法(不能是 undefined 或空对象)。

  • 安全做法:让 MongoDB 自动生成 _id(即 filter 不含 _id,update 也不显式设 _id)
  • 必须自定义 _id?那就把 _id 放进 filter 里,比如 { _id: ObjectId("...") },这样 upsert 才知道“按这个 _id 查,没有就插这个 _id”
  • 常见坑:用 new ObjectId() 生成新 id 写进 update,结果每次都不一样,等同于没 upsert

upsert 和 findAndModify 的原子性差异

updateOne + upsert: true 是服务端原子操作,但仅限单文档。如果你需要「查+改+返回旧值」或「多条件竞态控制」,就得用 findOneAndUpdate,它底层调用的是和 upsert 同一引擎,但多了返回控制。

错误认知:“upsert 能防止并发插入重复数据”——它只能防同一 filter 的并发,如果两个请求的 filter 看似不同但业务上等价(比如用邮箱和手机号分别查用户),MongoDB 无法识别,仍可能插入两条。

  • 并发安全的前提:filter 必须能精确表达业务唯一性,且对应字段有唯一索引(unique: true
  • 没唯一索引?即使 upsert 也挡不住两个请求同时判定“不存在”,然后都执行插入
  • 真正要强一致性,得配合应用层锁或数据库事务(4.0+ 副本集/5.0+ 分片集群支持 multi-document transaction)

最常被忽略的一点:upsert 的“存在判断”和“插入动作”之间没有间隙,但你的应用逻辑如果在 upsert 前先做了一次 find,再决定要不要 upsert,那就彻底失去原子性了——那不是 upsert,那是自己手写竞态。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
undefined是什么
undefined是什么

undefined是代表一个值或变量不存在或未定义的状态。它可以作为默认值来判断一个变量是否已经被赋值,也可以用于设置默认参数值。尽管在不同的编程语言中,undefined可能具有不同的含义和用法,但理解undefined的概念可以帮助我们更好地理解和编写程序。本专题为大家提供undefined相关的各种文章、以及下载和课程。

6623

2023.07.31

网页undefined是什么意思
网页undefined是什么意思

网页undefined是指页面出现了未知错误的意思,提示undefined一般是在开发网站的时候定义不正确或是转换不正确,或是找不到定义才会提示undefined未定义这个错误。想了解更多的相关内容,可以阅读本专题下面的文章。

3356

2024.08.14

网页undefined啥意思
网页undefined啥意思

本专题整合了undefined相关内容,阅读下面的文章了解更多详细内容。后续继续更新。

1718

2025.12.25

mongodb和mysql的区别
mongodb和mysql的区别

mongodb和mysql的区别:1、数据模型;2、查询语言;3、扩展性和性能;4、可靠性。本专题为大家提供mongodb和mysql的区别的相关的文章、下载、课程内容,供大家免费下载体验。

287

2023.07.18

mongodb启动命令
mongodb启动命令

MongoDB 是一种开源的、基于文档的 NoSQL 数据库管理系统。本专题提供mongodb启动命令的文章,希望可以帮到大家。

267

2023.08.08

MongoDB删除数据的方法
MongoDB删除数据的方法

MongoDB删除数据的方法有删除集合中的文档、删除整个集合、删除数据库和删除指定字段等。本专题为大家提供MongoDB相关的文章、下载、课程内容,供大家免费下载体验。

161

2023.09.19

常用的数据库软件
常用的数据库软件

常用的数据库软件有MySQL、Oracle、SQL Server、PostgreSQL、MongoDB、Redis、Cassandra、Hadoop、Spark和Amazon DynamoDB。更多关于数据库软件的内容详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1010

2023.11.02

mongodb有哪些应用领域
mongodb有哪些应用领域

mongodb 的应用领域涵盖广泛,包括内容管理系统、社交媒体、分析、移动应用、物联网、金融科技、医疗保健和广告技术等领域,因其灵活性、可扩展性和易用性而广受欢迎。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

345

2024.04.02

抖漫入口地址合集
抖漫入口地址合集

本专题整合了抖漫入口地址相关合集,阅读专题下面的文章了解更多详细地址。

17

2026.03.17

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号