![MongoDB进阶与实战:微服务整合、性能优化、架构管理](https://wfqqreader-1252317822.image.myqcloud.com/cover/697/38209697/b_38209697.jpg)
2.5 更新文档
2.5.1 update命令
可以用update命令对指定的数据进行更新,命令的格式如下:
![](https://epubservercos.yuewen.com/6F449D/20118171608699906/epubprivate/OEBPS/Images/40827_42_3.jpg?sign=1738867124-YFKCA2te6pweRTaX5eKHjGUKwlQppKhG-0-56274e071f9a052c2d9c0f52ca2600c9)
参数说明
● query:描述更新的查询条件;
● update:描述更新的动作及新的内容;
● options:描述更新的选项。
1.更新单个文档
如某个book文档被收藏了,则需要将该文档的favCount字段自增,代码如下:
![](https://epubservercos.yuewen.com/6F449D/20118171608699906/epubprivate/OEBPS/Images/40827_42_4.jpg?sign=1738867124-vsbZOGXVTP26aeMs8ZYrdP0uJT4K7AvF-0-ed70315c9eb800fdc10a1a20e33283af)
2.更新多个文档
默认情况下,update命令只在更新第一个文档之后返回,如果需要更新多个文档,则可以使用multi选项。
如下面的操作中,将分类为“novel”的文档的发布时间(publishedDate)调整到当前时间,代码如下:
![](https://epubservercos.yuewen.com/6F449D/20118171608699906/epubprivate/OEBPS/Images/40827_43_1.jpg?sign=1738867124-ADYZ2k8rnzbyzfGU908qrcvLEbjRhvfI-0-0d5d341631120f3d3c0eb78943b543b0)
3.使用upsert命令
upsert是一种特殊的更新,其表现为如果目标文档不存在,则执行插入命令,代码如下:
![](https://epubservercos.yuewen.com/6F449D/20118171608699906/epubprivate/OEBPS/Images/40827_43_2.jpg?sign=1738867124-IVi0DC33fIz4d6lrpmbZjgXGfKCgZdjT-0-f4b788f901d17cfac1100ae6695eaf0d)
该命令由于指定title的book文档不存在,因而会执行插入。从返回结果中可以看到,nMatched、nModified都为0,这表示没有文档被匹配及更新;nUpserted=1则提示执行了upsert动作,最终写入的文档由query和update限定符组成。
4.实现replace语义
update命令中的更新描述(update)通常由操作符描述,如果更新描述中不包含任何操作符,那么MongoDB会实现文档的replace语义,代码如下:
![](https://epubservercos.yuewen.com/6F449D/20118171608699906/epubprivate/OEBPS/Images/40827_44_1.jpg?sign=1738867124-b1xSt7OkbbioGqUSnQLyrO7RLdNAhCpq-0-e8b93dae0b898a1b48e72401e04bac4d)
替换后的文档如下:
![](https://epubservercos.yuewen.com/6F449D/20118171608699906/epubprivate/OEBPS/Images/40827_44_2.jpg?sign=1738867124-Svu5uG1GUNLjP3U55oLhhaLJsTNXTyDO-0-b872104d668567361da29d5afa72f519)
由于_id是不可变的,因此在更新描述中不用提供_id字段,如果提供了则必须保证和之前的文档一致,否则会提示错误。
update命令的选项配置较多,为了简化使用还可以使用一些快捷命令,具体如下:
● updateOne:更新单个文档。
● updateMany:更新多个文档。
● replaceOne:替换单个文档。
2.5.2 findAndModify命令
除了update命令,MongoDB还提供了一个特殊的命令:findAndModify。从命名上不难理解,findAndModify兼容了查询和修改指定文档的功能,下面介绍它的用法。
将某个book文档的收藏数(favCount)加1,代码如下:
![](https://epubservercos.yuewen.com/6F449D/20118171608699906/epubprivate/OEBPS/Images/40827_44_3.jpg?sign=1738867124-hhBt9QE6wJPTdKZu0oPqkpVC2TCR2ltl-0-2427830e0f027fa43b6ca7e0e14b0326)
该操作会返回符合查询条件的文档数据,并完成对文档的修改。
默认情况下,findAndModify会返回修改前的“旧”数据。如果希望返回修改后的数据,则可以指定new选项,代码如下:
![](https://epubservercos.yuewen.com/6F449D/20118171608699906/epubprivate/OEBPS/Images/40827_45_1.jpg?sign=1738867124-4vrARduksf9Xlxwk1w4ykVhECVSaJ75e-0-b4a17db3d6d4248651f4b1ef48e6b5ef)
findAndModify与update命令在使用方法上比较类似,共同点为:
● 单文档更新时可以保证原子性。
● 支持upsert模式。
然而,在结果行为方面,两者存在一些区别:
● findAndModify除了支持更新,还支持同时返回更新前或更新后的数据,而update只能返回WriteResult对象作为结果提示。
● findAndModify只能更新单个文档,而update在指定multi:true后可以更新多个文档。如果findAndModify匹配到了多个文档,则只会更新其第一个,可以通过设置sort条件来调整最终的结果。
与findAndModify语义相近的命令如下:
● findOneAndUpdate:更新单个文档并返回更新前(或更新后)的文档。
● findOneAndReplace:替换单个文档并返回替换前(或替换后)的文档。
2.5.3 更新操作符
更新操作符见表2-8。
表2-8 更新操作符
![](https://epubservercos.yuewen.com/6F449D/20118171608699906/epubprivate/OEBPS/Images/40827_45_2.jpg?sign=1738867124-1mswEIPCPrzhJlVbRac4gt5f9soTMhEE-0-c4603f3ac5b37ef353880115117b139f)
续表
![](https://epubservercos.yuewen.com/6F449D/20118171608699906/epubprivate/OEBPS/Images/40827_46_1.jpg?sign=1738867124-w6evIdjXK5qkEOtUpmKhUypqGpe2hTK6-0-f774475c9d8adda8cd82006967b0d0eb)