MongoDB中提供了三种更新集合中的文档的方式,分别是更新一条文档,更新多条文档和替换一条文档的方式,语法如下:

  1. db.collection.updateOne(filter, update, options);
  2. db.collection.updateMany(filter, update, options);
  3. db.collection.replaceOne(filter, replacement, options);

其中,

collection:指的是集合名称;

filter:必填,指的是过滤条件,与查询文档中的Query查询选择器是一样的,使用方式可参考查询文档;

update:必填,指的是更新的方式,也是我们更新文档需要重点关注的地方;

options:可选,指的是其他的选项;

一、更新一条文档

update参数语法:

{
    <operator1>: { <field1>: <value1>, ... },
    <operator2>: { <field2>: <value2>, ... },
    ...
}

我们以更新其中一个字段为例, 更新字段中的值使用的 operator 是 $set

例子:

查询集合中的数据:

{ "_id" : "1001", "name" : "张三", "fruits" : [ "apple", "orange" ] }
{ "_id" : "1002", "name" : "李四", "fruits" : [ "banana", "apple" ] }
{ "_id" : "1003", "name" : "王五", "fruits" : [ "banana", "apple", "orange" ] }

修改_id为1001的人员的姓名为张三2 :

db.test.updateOne(
    { "_id": "1001" }, 
    { $set: { "name": "张三2" } }
);

执行后查询集合中的数据:

{ "_id" : "1001", "name" : "张三2", "fruits" : [ "apple", "orange" ] }
{ "_id" : "1002", "name" : "李四", "fruits" : [ "banana", "apple" ] }
{ "_id" : "1003", "name" : "王五", "fruits" : [ "banana", "apple", "orange" ] }

执行修改操作后发现编号为1001的人员的姓名已经修改成了张三2。

二、Operator

我们已经了解到了如何修改一条数据,使用到了$set 操作,下面我们对操作字段的操作进行详细了解一下:

1、新增或修改字段($set)

语法:{ $set: { <field1>: <value1>, ... } }

此操作再刚刚更新一条文档的时候已经讲解过了,这里省略。

另外此操作也可以增加新字段并设置Value做为初始值

2、新增或修改更新时间($currentDate)

语法:{ $currentDate: { <field1>: <typeSpecification1>, ... } }

此操作可以设置当前时间作为数据的更新时间,可以将时间更新到已经存在的字段,也可以创建新的字段作为更新时间。

例子:

更新编号为1001的人员的最后修改时间:

db.test.updateOne(
    {"_id": "1001"}, 
    { $currentDate: { lastModified: true } 
});

查询所有数据如下:

{ "_id" : "1001", "name" : "张三2", "fruits" : [ "apple", "orange" ], "lastModified" : ISODate("2023-04-06T02:34:49.783Z") }
{ "_id" : "1002", "name" : "李四", "fruits" : [ "banana", "apple" ] }
{ "_id" : "1003", "name" : "王五", "fruits" : [ "banana", "apple", "orange" ] }

发现增加了最后修改时间的字段。

再次执行更新编号为1001的人员的最后修改时间查询的所有数据如下:

{ "_id" : "1001", "name" : "张三2", "fruits" : [ "apple", "orange" ], "lastModified" : ISODate("2023-04-06T02:36:00.703Z") }
{ "_id" : "1002", "name" : "李四", "fruits" : [ "banana", "apple" ] }
{ "_id" : "1003", "name" : "王五", "fruits" : [ "banana", "apple", "orange" ] }

发现时间发生了变化。所以此操作可以更新当前时间到字段,如果字段不存在则创建字段

3、增减($inc)

语法:{ $inc: { <field1>: <amount1>, <field2>: <amount2>, ... } }

此操作可以在原有字段值的基础上进行增减操作。

另外需要注意的是,如果字段不存在,则会新增字段并设置Value做为初始值

例子:

我们在原有数据的基础上增加一个成绩字段。

db.test.updateOne(
    {"_id": "1001"}, 
    { $set: { score: 100 } }
);

现在我们对成绩进行增加20分的操作:

db.test.updateOne(
    {"_id": "1001"}, 
    { $inc: { score: 20 } }
);

我们查询一下数据如下:

{ "_id" : "1001", "name" : "张三2", "fruits" : [ "apple", "orange" ], "lastModified" : ISODate("2023-04-06T02:36:00.703Z"), "score" : 120 }
{ "_id" : "1002", "name" : "李四", "fruits" : [ "banana", "apple" ] }
{ "_id" : "1003", "name" : "王五", "fruits" : [ "banana", "apple", "orange" ] }

发现成绩已经变成了120,增加成功了。

下面我们对成绩再进行减少40分的操作:

db.test.updateOne(
    {"_id": "1001"}, 
    { $inc: { score: -40 } }
);

我们查询一下数据如下:

{ "_id" : "1001", "name" : "张三2", "fruits" : [ "apple", "orange" ], "lastModified" : ISODate("2023-04-06T02:36:00.703Z"), "score" : 80 }
{ "_id" : "1002", "name" : "李四", "fruits" : [ "banana", "apple" ] }
{ "_id" : "1003", "name" : "王五", "fruits" : [ "banana", "apple", "orange" ] }

发现成绩已经变成了80,减少成功了。

扩展:此操作可以用作自增、自减

 4、移除字段($unset)

语法:{ $unset: { <field1>: "", ... } }

此操作可以移除指定的字段

例子:

下面我们移除成绩字段:

db.test.updateOne(
    {"_id": "1001"},
    { $unset: { score: "" } } 
);

查询一下数据如下:

{ "_id" : "1001", "name" : "张三2", "fruits" : [ "apple", "orange" ], "lastModified" : ISODate("2023-04-06T02:36:00.703Z") }
{ "_id" : "1002", "name" : "李四", "fruits" : [ "banana", "apple" ] }
{ "_id" : "1003", "name" : "王五", "fruits" : [ "banana", "apple", "orange" ] }

发现成绩字段已经被移除。

5、重命名字段($rename)

语法:{$rename: { <field1>: <newName1>, <field2>: <newName2>, ... } }

例子:

下面我们将最后更新时间字段lastModified重命名成updateTime:

db.test.updateOne(
    {"_id": "1001"},
    { $rename: { "lastModified": "updateTime" } } 
);

查询一下数据如下:

{ "_id" : "1001", "name" : "张三2", "fruits" : [ "apple", "orange" ], "updateTime" : ISODate("2023-04-06T02:36:00.703Z") }
{ "_id" : "1002", "name" : "李四", "fruits" : [ "banana", "apple" ] }
{ "_id" : "1003", "name" : "王五", "fruits" : [ "banana", "apple", "orange" ] }

发现更新时间字段已经重命名成功。

6、插入时设置($setOnInsert)

语法:

db.collection.updateOne(
   <query>,
   { $setOnInsert: { <field1>: <value1>, ... } },
   { upsert: true }
)

此操作类似于新增数据后进行初始化操作。

说明:upsert:true 代表如果未找到待更新的数据则执行插入操作。

例子:

更新编号为1004的用户,初始化成绩为100:

db.test.updateOne(
    {"_id": "1004"},
    { $set: { "name": "田七" }, $setOnInsert: { score: 100 } }, 
    { upsert: true} 
);

查询数据如下:

{ "_id" : "1001", "name" : "张三2", "fruits" : [ "apple", "orange" ], "updateTime" : ISODate("2023-04-06T02:36:00.703Z") }
{ "_id" : "1002", "name" : "李四", "fruits" : [ "banana", "apple" ] }
{ "_id" : "1003", "name" : "王五", "fruits" : [ "banana", "apple", "orange" ] }
{ "_id" : "1004", "name" : "田七", "score" : 100 }

下面我们以此更新编号为1001的用户:

db.test.updateOne(
    {"_id": "1001"},
    { $set: { "name": "田七" }, $setOnInsert: { score: 100 } }, 
    { upsert: true} 
);

查询数据如下:

{ "_id" : "1001", "name" : "田七", "fruits" : [ "apple", "orange" ], "updateTime" : ISODate("2023-04-06T02:36:00.703Z") }
{ "_id" : "1002", "name" : "李四", "fruits" : [ "banana", "apple" ] }
{ "_id" : "1003", "name" : "王五", "fruits" : [ "banana", "apple", "orange" ] }
{ "_id" : "1004", "name" : "田七", "score" : 100 }

发现操作仅对新增数据有效,类似于新增数据后初始化字段,另外$set中的字段也会添加到新增的数据中。

三、Options

1、upsert

true 代表如果未找到待更新的数据则执行插入操作。

false 代表始终不执行插入操作。

默认值为 false

此选项不再写示例进行介绍,可以参考上面提到的 $setOnInsert 操作