MongoDB 基础系列十五:增删查改 CRUD 之 Query - Update

前言

此篇博文是 Mongdb 基础系列之一;

本文为作者的原创作品,转载需注明出处;

简介

本文将会介绍如何使用下述方法通过 mongo shell 对文档进行 update 操作;

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

为了演示本章的功能,假设我们有如下的测试用例,

1
2
3
4
5
6
7
8
9
10
11
12
db.inventory.insertMany( [
{ item: "canvas", qty: 100, size: { h: 28, w: 35.5, uom: "cm" }, status: "A" },
{ item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
{ item: "mat", qty: 85, size: { h: 27.9, w: 35.5, uom: "cm" }, status: "A" },
{ item: "mousepad", qty: 25, size: { h: 19, w: 22.85, uom: "cm" }, status: "P" },
{ item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "P" },
{ item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" },
{ item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" },
{ item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" },
{ item: "sketchbook", qty: 80, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
{ item: "sketch pad", qty: 95, size: { h: 22.85, w: 30.5, uom: "cm" }, status: "A" }
]);

Update Document in a Collection

MongoDB 提供了相关的 update operators

Update a Single Document

1
2
3
4
5
6
7
db.inventory.updateOne(
{ item: "paper" },
{
$set: { "size.uom": "cm", status: "P" },
$currentDate: { lastModified: true }
}
)

上述方法使用 db.inventory.updateOne() 方法对 inventory collection 的第一个 item 元素等于 paper 的 document 进行更新操作;上面的更新操作对匹配的 document 执行如下的操作,

  • 使用 $set 操作将 size.uom 字段的值更新为 “cm” 以及将 status 字段的值更新为 “P”
  • 使用 $currentDate 操作符将字段 lastModified 更新为当前日期;如果 lastModified 字段不存在,$currentDate 将会创建该字段;

需要注意的是,updateOne() 方法的第一个参数值是匹配条件;

Update Multiple Documents

New in version 3.2.

下面的这个例子使用 db.collection.updateMany() 方法对 inventory collection 进行更新操作,匹配的条件是 qty 的值小于 50;

1
2
3
4
5
6
7
db.inventory.updateMany(
{ "qty": { $lt: 50 } },
{
$set: { "size.uom": "in", status: "P" },
$currentDate: { lastModified: true }
}
)

对匹配的 documents 进行的相关操作如下,

  • 使用 $set 操作符将相关的 documents 的 size.uom 字段的值更新为 “in” 同时将 status 字段的值更新为 “P”
  • 使用 $currentDate 操作符将字段 lastModified 更新为当前日期;如果 lastModified 字段不存在,$currentDate 将会创建该字段;

这里与 Update a Single Document 的唯一的区别是,这里是一次性对所有匹配的文档做更新操作而不是匹配的第一个 document;

Replace a Document

如果是要替换整个文档内容,除了 _id 字段,那么只需要将新的文档作为第二个参数调用 db.collection.replaceOne() 方法即可;

需要注意的是,用来替换旧有 document 的新 document 可以拥有与旧 document 不相同的字段,在新的 document 中,你可以省略掉 _id 字段,因为 _id 字段是不可变的;不过,如果你坚持要传入 _id 字段,那么必须保证当前 document 与旧有的 document 的 _id 值必须相同;

下面这个例子将会使用新的 document 替换第一个匹配 filter condition { item: “paper” } 的原有 document,

1
2
3
4
db.inventory.replaceOne(
{ item: "paper" },
{ item: "paper", instock: [ { warehouse: "A", qty: 60 }, { warehouse: "B", qty: 40 } ] }
)

这里要特别注意的是第二个参数,是一个新的,完整的 document 内容,

1
{ item: "paper", instock: [ { warehouse: "A", qty: 60 }, { warehouse: "B", qty: 40 } ] }

特性

Atomicity

All write operations in MongoDB are atomic on the level of a single document. For more information on MongoDB and atomicity, see Atomicity and Transactions.

_id Field

Once set, you cannot update the value of the _id field nor can you replace an existing document with a replacement document that has a different _id field value.

一句话就是,如果 _id 一旦设置,无论如何也不能被修改了,不管是对其进行 udpate 操作还是 replace 操作;

Document Size

When performing update operations that increase the document size beyond the allocated space for that document, the update operation relocates the document on disk.

当更新操作使得文档增大且超过了为其分配的空间,那么将会进行重新分配,分配到新的磁盘上;

Field Order

MongoDB 将会保留写入文档的字段顺序,不过 _id 例外,_id 始终是排在最前面,

这个特性是在 Version 2.6 和之后加入的,Version 2.6 以前 MongoDB 并不会保留文档字段的顺序;

Upsert 选项

如果在执行 updateOne(), updateMany(), 或者 replaceOne() 操作的时候,添加了选项 Upsert : true,并且如果没有任何文档匹配了更新的条件,那么该更新操作将会创建一个新的 document 并插入到当前的 collection 中;如果匹配了更新的条件,那么还是按照原来的逻辑进行操作;

Write Acknowledgement

With write concerns, you can specify the level of acknowledgement requested from MongoDB for write operations. For details, see Write Concern.