你知道mongoose中的 __v么

简介: mongoose 在添加数据的时候,会默认给你加上一个属性__v,这个属性的全称是__version,顾名思义是版本的意思,作用是给每一个文档加上版本控制,防止并发来修改数据库的数据。

mongoose 在添加数据的时候,会默认给你加上一个属性__v,这个属性的全称是__version,顾名思义是版本的意思,作用是给每一个文档加上版本控制,防止并发来修改数据库的数据。


d2da5228954800a15757e0aa70fe7543.png


mongoose中的并发管理


在mongoose中,我们可以会有以下操作:


a43b120033196e62a271c4cf868c57c6.png


当多个异步函数同时操作数据库时,就可能发生这样的情况,具体的场景往往发生在并发请求中


面对这种情况,mongoose作出以下假设:


  • 当修改一个文档时,如果某些字段已经不再和数据库对应,说明这个字段的数据是脏数据(dirty data),对于脏数据,不应该对数据库产生影响


  • 当修改一个文档时,如果字段和数据库是对应的,则是正常数据,正常数据可以正常的更改数据库


修改普通字段


执行以下代码:


async function  findById(){
 const stu1 = await StuSchema.findById('6187c8599cf04703abb24c20');
 stu1.stuNo = '20210103';
 stu1.name = 'twinkle';
 await stu1.save();
 const stu2 = await StuSchema.findById('6187c8599cf04703abb24c20');
 stu2.age = 20;
 await stu2.save(); 
}
findById();
复制代码

dbe072653bc9a51c45a33e3c0e995857.png


因此,mongoose对于上述场景的处理如下:


3721cb3a0dfb107ced40da527068490b.png


可以看出,对于user2的修改,name和loginId是脏数据,因此不会更新到数据库中,而age是正常数据,对它的更改会应用到数据库


修改数组


然而,mongoose无法准确的判定对数组是否是脏数据,因此,如果遇到数组的修改,mongoose会做出如下处理:


  • 当新增文档时,会自动添加字段__v,用于记录更新版本号,一开始为0
  • 通过模型实例对数组进行修改后,保存时会在内部调用实例的increment函数,将版本号+1
  • 当其他模型实例也更改了数组,保存时会对比版本号,如果不一致,则会引发VersionError


执行以下代码:


async function  findById(){
 const stu1 = await StuSchema.findById('6187c8599cf04703abb24c20');
 const stu2 = await StuSchema.findById('6187c8599cf04703abb24c20');
 stu1.loves = ['code1'];
 await stu1.save();
 stu2.loves = ['game1'];
 await stu2.save();
}
findById();
复制代码

09ce221c9efc1fefd76da22a3b75807f.png


数据库结果


2c1bc577a0ea41550f64166e9b28bb68.png


原理图如下:


160461cace15c4b2132aa46a92daeb2e.png


出现错误是好事,可以提醒开发者:这一次保存的某些数据是脏数据,应该引起重视。开发者可以灵活的根据具体情况作出处理,比如提示用户保存失败,或者重新获取数据然后保存。


由于mongoose仅针对数组进行版本控制,如果要针对所有字段都进行版本控制,需要使用mongoose的插件:mongoose-update-if-current


插件地址:github.com/eoin-obrien…


使用插件后,所有的字段都将受到版本控制,一旦版本不一致,将引发VersionError

相关文章
|
缓存 开发框架 监控
优化后端服务响应时间的关键策略与实践
在当今数字化时代,优化后端服务响应时间至关重要。本文探讨了几种关键策略和实践方法,帮助开发团队提高系统性能和用户体验。通过合理的资源分配、技术选型和代码优化,可以有效缩短响应时间,提升系统的整体效率和稳定性。【7月更文挑战第5天】
537 0
|
人工智能 安全 搜索推荐
新手指南:人工智能poe ai 怎么用?国内使用poe记住这个方法就够了!
由于国内网络限制,许多用户在尝试访问Poe AI时面临障碍。幸运的是,现在国内用户也能轻松畅玩Poe AI,告别繁琐的设置,直接开启AI创作之旅!🎉
1351 13
|
关系型数据库 MySQL 数据库
|
存储 容灾 NoSQL
同城双活的必修课 - 落地经验与关键挑战解析
同城双活作为一种容灾架构,通过在同一城市建立两个数据中心,以确保在一个数据中心发生故障时,系统能够快速切换到另一个数据中心,从而提高系统的可用性
1924 2
同城双活的必修课 - 落地经验与关键挑战解析
分布式系列教程(25) -解决Zookeeper启动失败的问题
分布式系列教程(25) -解决Zookeeper启动失败的问题
784 0
|
移动开发 JavaScript 前端开发
HTML5 Web Workers详解
HTML5 Web Workers 允许在后台线程中运行 JavaScript,实现复杂计算而不影响用户界面,提升应用性能。其主要特性包括并行处理、异步通信、独立作用域及多数据类型支持。通过创建和使用 Worker 文件,如 `worker.js`,可执行后台任务,并与主线程通过消息传递机制通信。适用于数据处理、图像处理、复杂计算及网络请求并行等场景。需要注意的是,Web Workers 在浏览器兼容性、安全性限制、调试及资源消耗方面需特别关注。合理利用 Web Workers 可显著增强 Web 应用的流畅度和响应速度。
|
Windows
Windows平台如何修改监听的服务名称?
【8月更文挑战第15天】在Windows平台上可透过注册表编辑器、命令提示符或第三方工具修改服务的显示名称。首先,通过注册表编辑器找到`HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services`下的目标服务,修改其“DisplayName”键值。或者,在命令提示符中使用`sc config`命令来变更服务名称。此外,利用第三方工具如Windows Service Manager也能简化此过程。修改前请确保了解可能的影响并做好备份。
916 4
|
消息中间件 前端开发 Java
阿里中间件seata源码剖析一:聊聊RM和TM客户端初始化
阿里中间件seata源码剖析一:聊聊RM和TM客户端初始化
519 81
阿里中间件seata源码剖析一:聊聊RM和TM客户端初始化
|
测试技术 编译器 PHP
PHP 7与PHP 8的性能比较
本文通过对比分析PHP 7和PHP 8在不同场景下的性能表现,揭示新版本在执行速度、内存占用等方面的改进。利用实际测试数据支撑结论,为开发者提供升级决策的依据。
|
Docker 容器
Docker Desktop镜像迁移到其他磁盘
Docker Desktop镜像迁移到其他磁盘
591 0

热门文章

最新文章