MongoDB创建、更新和删除文档
1. 插入文档
1.1 insertOne() - 插入单个文档
语法:
javascript
db.collection.insertOne(
<document>,
{
writeConcern: <document>
}
)
参数说明:
document:要插入的文档对象writeConcern:写入关注级别(可选),控制写入的确认程度
返回值 :
返回一个 InsertOneResult 对象,包含 acknowledged 和 insertedId 字段。
示例:
javascript
// 插入一个用户文档
db.users.insertOne({
name: "张三",
age: 25,
email: "zhangsan@example.com",
status: "active"
})
// 插入带嵌套文档的数据
db.orders.insertOne({
orderId: "ORD001",
userId: 1,
items: [
{ product: "笔记本", quantity: 2, price: 39.99 },
{ product: "钢笔", quantity: 5, price: 5.99 }
],
total: 109.93,
created: new Date()
})
1.2 insertMany() - 插入多个文档
语法:
javascript
db.collection.insertMany(
[ <document1>, <document2>, ... ],
{
ordered: <boolean>,
writeConcern: <document>
}
)
参数说明:
ordered:默认为true,表示按顺序插入,如果某个文档插入失败,后续文档将不会继续插入;设为false时,即使某些文档失败,其他文档仍会继续插入writeConcern:写入关注级别(可选)
返回值 :
返回一个 InsertManyResult 对象,包含 acknowledged 和 insertedIds 数组。
示例:
javascript
// 插入多个用户(有序插入)
db.users.insertMany([
{ name: "李四", age: 28, email: "lisi@example.com" },
{ name: "王五", age: 32, email: "wangwu@example.com" },
{ name: "赵六", age: 24, email: "zhaoliu@example.com" }
])
// 无序插入(即使某个文档重复也不会影响其他文档)
db.users.insertMany([
{ _id: 1, name: "张三", age: 25 },
{ _id: 2, name: "李四", age: 28 },
{ _id: 1, name: "重复ID", age: 30 } // 这个会失败,但不影响后面的文档
], { ordered: false })
1.3 插入文档的重要注意事项
-
自动生成
_id:- 如果插入的文档没有包含
_id字段,MongoDB 会自动生成一个ObjectId类型的唯一标识符 - 如果手动指定了
_id,必须确保其在集合中是唯一的
- 如果插入的文档没有包含
-
文档大小限制:
- 单个文档大小不能超过 16MB(BSON 文档大小限制)
-
数据类型自动转换:
- MongoDB 会根据值的类型自动存储为相应的 BSON 类型
-
插入性能优化:
- 批量插入(
insertMany)比循环调用insertOne性能更好 - 批量插入时,建议每批不超过 1000 个文档
- 批量插入(
2. 删除文档
2.1 deleteOne() - 删除单个文档
语法:
javascript
db.collection.deleteOne(
<filter>,
{
writeConcern: <document>,
collation: <document>,
hint: <document|string>
}
)
参数说明:
filter:删除条件,匹配的第一个文档将被删除writeConcern:写入关注级别(可选)collation:指定语言比较规则(可选)hint:指定使用的索引(可选)
返回值 :
返回一个 DeleteResult 对象,包含:
acknowledged:操作是否被确认deletedCount:删除的文档数量(最多为 1)
示例:
javascript
// 删除年龄为 25 的第一个用户
db.users.deleteOne({ age: 25 })
// 删除指定 ID 的用户
db.users.deleteOne({ _id: ObjectId("507f1f77bcf86cd799439011") })
// 使用索引提示删除
db.users.deleteOne(
{ status: "inactive" },
{ hint: "status_1" }
)
2.2 deleteMany() - 删除多个文档
语法:
javascript
db.collection.deleteMany(
<filter>,
{
writeConcern: <document>,
collation: <document>
}
)
参数说明:
filter:删除条件,匹配的所有文档都会被删除writeConcern:写入关注级别(可选)collation:指定语言比较规则(可选)
返回值 :
返回一个 DeleteResult 对象,包含 deletedCount 表示删除的文档数量。
示例:
javascript
// 删除所有状态为 inactive 的用户
db.users.deleteMany({ status: "inactive" })
// 删除年龄大于 60 的所有用户
db.users.deleteMany({ age: { $gt: 60 } })
// 删除所有文档(清空集合)
db.users.deleteMany({})
2.3 删除文档的重要注意事项
-
删除操作不可逆:
- 删除操作默认没有回收站功能,建议在删除前先使用
find()确认条件
- 删除操作默认没有回收站功能,建议在删除前先使用
-
集合与数据库的删除:
- 删除所有文档不会删除集合本身和索引
- 如需删除整个集合,可使用
db.collection.drop()
-
性能考虑:
- 大量删除会影响数据库性能,建议分批删除或使用
db.collection.drop()后重建集合 - 删除操作会占用系统资源,建议在业务低峰期执行
- 大量删除会影响数据库性能,建议分批删除或使用
-
事务支持:
- 在复制集和分片集群中,删除操作可以参与多文档事务(MongoDB 4.0+)
3. 更新文档
3.1 updateOne() - 更新单个文档
语法:
javascript
db.collection.updateOne(
<filter>,
<update>,
{
upsert: <boolean>,
writeConcern: <document>,
collation: <document>,
arrayFilters: [ <filterdocument1>, ... ],
hint: <document|string>
}
)
参数说明:
filter:更新条件update:更新操作(必须使用更新运算符)upsert:设为true时,如果没有匹配的文档,则插入新文档arrayFilters:用于更新数组元素的条件hint:指定使用的索引
更新运算符:
| 运算符 | 说明 | 示例 |
|---|---|---|
$set |
设置字段值 | { $set: { age: 30 } } |
$unset |
删除字段 | { $unset: { email: "" } } |
$inc |
数值增减 | { $inc: { age: 1 } } |
$mul |
数值相乘 | { $mul: { salary: 1.1 } } |
$rename |
重命名字段 | { $rename: { "name": "fullName" } } |
$setOnInsert |
仅在插入时设置字段 | { $setOnInsert: { created: new Date() } } |
$min |
更新为较小值 | { $min: { age: 25 } } |
$max |
更新为较大值 | { $max: { age: 60 } } |
示例:
javascript
// 更新单个字段
db.users.updateOne(
{ name: "张三" },
{ $set: { age: 26 } }
)
// 使用 upsert:如果不存在则插入
db.users.updateOne(
{ email: "newuser@example.com" },
{ $set: { name: "新用户", age: 20, status: "active" } },
{ upsert: true }
)
// 数值增减
db.products.updateOne(
{ sku: "ABC123" },
{ $inc: { quantity: -5 } } // 减少5个库存
)
// 更新数组中的特定元素
db.users.updateOne(
{ _id: 1, "items.name": "笔记本" },
{ $set: { "items.$.price": 45.99 } }
)
3.2 updateMany() - 更新多个文档
语法:
javascript
db.collection.updateMany(
<filter>,
<update>,
{
upsert: <boolean>,
writeConcern: <document>,
collation: <document>,
arrayFilters: [ <filterdocument1>, ... ]
}
)
示例:
javascript
// 将所有状态为 active 的用户的等级提升1级
db.users.updateMany(
{ status: "active" },
{ $inc: { level: 1 } }
)
// 为所有年龄小于 18 的用户添加未成年人标记
db.users.updateMany(
{ age: { $lt: 18 } },
{ $set: { isMinor: true } }
)
// 批量重命名字段
db.users.updateMany(
{},
{ $rename: { "userName": "username" } }
)
3.3 replaceOne() - 替换文档
语法:
javascript
db.collection.replaceOne(
<filter>,
<replacement>,
{
upsert: <boolean>,
writeConcern: <document>,
collation: <document>,
hint: <document|string>
}
)
重要说明:
replaceOne会完全替换匹配的文档(_id字段除外)- 不能使用更新运算符,必须提供完整的替换文档
示例:
javascript
// 完全替换用户文档
db.users.replaceOne(
{ _id: 1 },
{
_id: 1, // _id 保持不变
name: "张三",
email: "zhangsan_new@example.com",
age: 26,
updatedAt: new Date()
}
)
3.4 更新文档的重要注意事项
-
原子性:
- 对单个文档的更新操作是原子性的
- 多个文档的更新不是原子性的,可能需要在应用层处理
-
更新运算符 vs 替换:
- 使用更新运算符(
$set、$inc等)进行部分更新 - 需要完全替换文档时使用
replaceOne
- 使用更新运算符(
-
性能优化:
- 更新操作会移动文档(如果文档大小增加),建议预留足够的空间
- 使用索引可以提升更新操作的性能
-
文档大小限制:
- 更新后文档大小不能超过 16MB
- 如果更新导致文档大小增加,可能触发文档迁移(影响性能)
-
返回值信息:
javascript// 获取更新结果 var result = db.users.updateOne( { name: "张三" }, { $set: { age: 26 } } ) print("匹配文档数: " + result.matchedCount) print("修改文档数: " + result.modifiedCount) print("是否插入新文档: " + result.upsertedId)
4. 综合示例与最佳实践
4.1 批量操作综合示例
javascript
// 创建测试集合
db.employees.insertMany([
{ name: "张三", dept: "技术部", salary: 8000, status: "active", level: 1 },
{ name: "李四", dept: "销售部", salary: 6000, status: "active", level: 1 },
{ name: "王五", dept: "技术部", salary: 7500, status: "inactive", level: 2 },
{ name: "赵六", dept: "市场部", salary: 6500, status: "active", level: 1 }
])
// 批量更新:所有技术部员工加薪10%
db.employees.updateMany(
{ dept: "技术部" },
{ $mul: { salary: 1.1 } }
)
// 批量更新:所有活跃员工等级+1
db.employees.updateMany(
{ status: "active" },
{ $inc: { level: 1 } }
)
// 删除所有非活跃员工
db.employees.deleteMany({ status: "inactive" })
4.2 最佳实践总结
| 场景 | 推荐方法 | 原因 |
|---|---|---|
| 插入单个文档 | insertOne() |
简洁、清晰 |
| 批量插入 | insertMany() |
性能更好,减少网络往返 |
| 删除单条记录 | deleteOne() |
明确意图 |
| 清空集合 | deleteMany({}) 或 drop() |
drop() 更快但会删除索引 |
| 更新单条记录 | updateOne() |
精确控制 |
| 批量更新 | updateMany() |
高效处理 |
| 存在则更新,不存在则插入 | updateOne() + upsert: true |
避免额外查询 |
| 完全替换文档 | replaceOne() |
语义清晰 |
总结
本章详细介绍了 MongoDB 中文档的三大核心操作:插入 、删除 和 更新。掌握这些操作是使用 MongoDB 的基础,重点包括:
- 插入操作的批量优化与
_id自动生成机制 - 删除操作的条件精确匹配与性能考虑
- 更新操作的多种运算符组合与
upsert模式 - 各种操作的返回值解析与错误处理
在实际开发中,应根据业务场景选择合适的操作方法,并注意索引优化和文档大小限制,以确保数据库操作的性能和稳定性。