![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=1739266500-50kwjP4BK4YdGgj2kgFbi2W3RN51CARE-0-cdea9e15cfc732f1d1e236c9c07b3e58)
参数说明
● query:描述更新的查询条件;
● update:描述更新的动作及新的内容;
● options:描述更新的选项。
1.更新单个文档
如某个book文档被收藏了,则需要将该文档的favCount字段自增,代码如下:
![](https://epubservercos.yuewen.com/6F449D/20118171608699906/epubprivate/OEBPS/Images/40827_42_4.jpg?sign=1739266500-LjlLNgSqEihlkAhaHyaOD9RR7syr5K91-0-7caad7ed96efedd926c49b8dadeae797)
2.更新多个文档
默认情况下,update命令只在更新第一个文档之后返回,如果需要更新多个文档,则可以使用multi选项。
如下面的操作中,将分类为“novel”的文档的发布时间(publishedDate)调整到当前时间,代码如下:
![](https://epubservercos.yuewen.com/6F449D/20118171608699906/epubprivate/OEBPS/Images/40827_43_1.jpg?sign=1739266500-hmMcTy0D33uROybb3lUAk5bfBN5Fdktd-0-ef5816ddae9fabf8c970174211646447)
3.使用upsert命令
upsert是一种特殊的更新,其表现为如果目标文档不存在,则执行插入命令,代码如下:
![](https://epubservercos.yuewen.com/6F449D/20118171608699906/epubprivate/OEBPS/Images/40827_43_2.jpg?sign=1739266500-atgqtGeTouJMXbVxw1IjkQZeLQcLu9Tn-0-b804c55b1e45ff8b9dd0ff764960c340)
该命令由于指定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=1739266500-bKAOvSqeqiSUwAsrk8ydkiQuUBRvSTqh-0-60c355bb2283b439617f11bb06c95ca0)
替换后的文档如下:
![](https://epubservercos.yuewen.com/6F449D/20118171608699906/epubprivate/OEBPS/Images/40827_44_2.jpg?sign=1739266500-LWABBuc3c7GHDXGlxeej4Kye8tnyHl2c-0-fdcc70ecbd740021d1dad7fd2b584b54)
由于_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=1739266500-OCAo8MZlrEzVy2RhJA9PE62wL6yDC9UY-0-97c08c098939cf8b3248f0dd87e3e2a5)
该操作会返回符合查询条件的文档数据,并完成对文档的修改。
默认情况下,findAndModify会返回修改前的“旧”数据。如果希望返回修改后的数据,则可以指定new选项,代码如下:
![](https://epubservercos.yuewen.com/6F449D/20118171608699906/epubprivate/OEBPS/Images/40827_45_1.jpg?sign=1739266500-CXdwYes3m8WfBQ5Brj8P2XTuefmw439q-0-9bcad9f4c97058ef062374dd5f700e6b)
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=1739266500-U0mwB0aefwNWvGkpwjvIqzyLxd03VyIt-0-86d35b4d929b5b1ae5ce8b8ad07877b3)
续表
![](https://epubservercos.yuewen.com/6F449D/20118171608699906/epubprivate/OEBPS/Images/40827_46_1.jpg?sign=1739266500-XRyuM2nsCXC9MtpnmuEmMMobfYtVRCJ0-0-56647833b4873354febb7b7d97214e2a)