MongoDB 的 CRUD 操作
MongoDB 的 CRUD 操作
一、基本 CRUD 操作
MongoDB 的 CRUD 操作是针对 document 的读写操作。
Create 操作
MongoDB 提供以下操作向一个 collection 插入 document
db.collection.insertOne()
:插入一条 documentdb.collection.insertMany()
:插入多条 document
注:以上操作都是原子操作。
插入操作的特性:
- MongoDB 中的所有写操作都是单个文档级别的原子操作。
- 如果要插入的 collection 当前不存在,则插入操作会自动创建 collection。
- 在 MongoDB 中,存储在集合中的每个文档都需要一个唯一的
_id
字段作为主键。如果插入的文档省略_id
字段,则 MongoDB 驱动程序会自动为_id
字段生成 ObjectId。 - 可以 MongoDB 写入操作的确认级别来控制写入行为。
【示例】插入一条 document 示例
1 | db.inventory.insertOne({ |
【示例】插入多条 document 示例
1 | db.inventory.insertMany([ |
Read 操作
MongoDB 提供 db.collection.find()
方法来检索 document。
Update 操作
MongoDB 提供以下操作来更新 collection 中的 document
db.collection.updateOne()
:更新一条 documentdb.collection.updateMany()
:更新多条 documentdb.collection.replaceOne()
:替换一条 document
语法格式:
db.collection.updateOne(<filter>, <update>, <options>)
db.collection.updateMany(<filter>, <update>, <options>)
db.collection.replaceOne(<filter>, <update>, <options>)
【示例】插入测试数据
1 | db.inventory.insertMany([ |
【示例】更新一条 document
1 | db.inventory.updateOne( |
【示例】更新多条 document
1 | db.inventory.updateMany( |
【示例】替换一条 document
1 | db.inventory.replaceOne( |
更新操作的特性:
- MongoDB 中的所有写操作都是单个文档级别的原子操作。
- 一旦设置了,就无法更新或替换
_id
字段。 - 除以下情况外,MongoDB 会在执行写操作后保留文档字段的顺序:
_id
字段始终是文档中的第一个字段。- 包括重命名字段名称的更新可能导致文档中字段的重新排序。
- 如果更新操作中包含
upsert : true
并且没有 document 匹配过滤器,MongoDB 会新插入一个 document;如果有匹配的 document,MongoDB 会修改或替换这些 document。
Delete 操作
MongoDB 提供以下操作来删除 collection 中的 document
db.collection.deleteOne()
:删除一条 documentdb.collection.deleteMany()
:删除多条 document
删除操作的特性:
- MongoDB 中的所有写操作都是单个文档级别的原子操作。
二、批量写操作
MongoDB 通过 db.collection.bulkWrite()
方法来支持批量写操作(包括批量插入、更新、删除)。
此外,db.collection.insertMany()
方法支持批量插入操作。
有序和无序的操作
批量写操作可以有序或无序。
- 对于有序列表,MongoDB 串行执行操作。如果在写操作的处理过程中发生错误,MongoDB 将不处理列表中剩余的写操作。
- 对于无序列表,MongoDB 可以并行执行操作,但是不能保证此行为。如果在写操作的处理过程中发生错误,MongoDB 将继续处理列表中剩余的写操作。
在分片集合上执行操作的有序列表通常比执行无序列表要慢,因为对于有序列表,每个操作必须等待上一个操作完成。
默认情况下,bulkWrite()
执行有序操作。要指定无序写操作,请在选项文档中设置 ordered : false
。
bulkWrite() 方法
bulkWrite()
支持以下写操作:
【示例】批量写操作示例
1 | try { |
批量写操作策略
大量的插入操作(包括初始数据插入或常规数据导入)可能会影响分片集群的性能。对于批量插入,请考虑以下策略:
预拆分 collection
如果分片集合为空,则该集合只有一个初始 chunk,该 chunk 位于单个分片上。然后,MongoDB 必须花一些时间来接收数据,创建拆分并将拆分的块分发到可用的分片。为了避免这种性能成本,您可以按照拆分群集中的拆分块中的说明预拆分 collection。
无序写操作
要提高对分片集群的写入性能,请使用 bulkWrite()
,并将可选参数顺序设置为 false。mongos
可以尝试同时将写入操作发送到多个分片。对于空集合,首先按照分片群集中的分割 chunk 中的说明预拆分 collection。
避免单调节流
如果在一次插入操作中,分片 key 单调递增,那么所有的插入数据都会存入 collection 的最后一个 chunk,也就是存入一个分片中。因此,集群的插入容量将永远不会超过该单个分片的插入容量。
如果插入量大于单个分片可以处理的插入量,并且无法避免单调递增的分片键,那么请考虑对应用程序进行以下修改:
- 反转分片密钥的二进制位。这样可以保留信息,并避免将插入顺序与值序列的增加关联起来。
- 交换第一个和最后一个 16 位字以“随机”插入。
SQL 和 MongoDB 对比
术语和概念
SQL 术语和概念 | MongoDB 术语和概念 |
---|---|
database | database |
table | collection |
row | document 或 BSON |
column | field |
index | index |
table joins | $lookup 、嵌入式文档 |
primary key | primary key MongoDB 中自动设置主键为 _id 字段 |
aggregation (e.g. group by) | aggregation pipeline 参考 SQL to Aggregation Mapping Chart. |
SELECT INTO NEW_TABLE | $out 参考 SQL to Aggregation Mapping Chart |
MERGE INTO TABLE | $merge (MongoDB 4.2 开始支持)参考 SQL to Aggregation Mapping Chart. |
UNION ALL | $unionWith (MongoDB 4.4 开始支持) |
transactions | transactions |