MongoDB入门学习教程,从入门到精通,MongoDB创建、更新和删除文档(3)

MongoDB创建、更新和删除文档

1. 插入文档

1.1 insertOne() - 插入单个文档

语法

javascript 复制代码
db.collection.insertOne(
  <document>,
  {
    writeConcern: <document>
  }
)

参数说明

  • document:要插入的文档对象
  • writeConcern:写入关注级别(可选),控制写入的确认程度

返回值

返回一个 InsertOneResult 对象,包含 acknowledgedinsertedId 字段。

示例

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 对象,包含 acknowledgedinsertedIds 数组。

示例

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 插入文档的重要注意事项

  1. 自动生成 _id

    • 如果插入的文档没有包含 _id 字段,MongoDB 会自动生成一个 ObjectId 类型的唯一标识符
    • 如果手动指定了 _id,必须确保其在集合中是唯一的
  2. 文档大小限制

    • 单个文档大小不能超过 16MB(BSON 文档大小限制)
  3. 数据类型自动转换

    • MongoDB 会根据值的类型自动存储为相应的 BSON 类型
  4. 插入性能优化

    • 批量插入(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 删除文档的重要注意事项

  1. 删除操作不可逆

    • 删除操作默认没有回收站功能,建议在删除前先使用 find() 确认条件
  2. 集合与数据库的删除

    • 删除所有文档不会删除集合本身和索引
    • 如需删除整个集合,可使用 db.collection.drop()
  3. 性能考虑

    • 大量删除会影响数据库性能,建议分批删除或使用 db.collection.drop() 后重建集合
    • 删除操作会占用系统资源,建议在业务低峰期执行
  4. 事务支持

    • 在复制集和分片集群中,删除操作可以参与多文档事务(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 更新文档的重要注意事项

  1. 原子性

    • 对单个文档的更新操作是原子性的
    • 多个文档的更新不是原子性的,可能需要在应用层处理
  2. 更新运算符 vs 替换

    • 使用更新运算符($set$inc 等)进行部分更新
    • 需要完全替换文档时使用 replaceOne
  3. 性能优化

    • 更新操作会移动文档(如果文档大小增加),建议预留足够的空间
    • 使用索引可以提升更新操作的性能
  4. 文档大小限制

    • 更新后文档大小不能超过 16MB
    • 如果更新导致文档大小增加,可能触发文档迁移(影响性能)
  5. 返回值信息

    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 模式
  • 各种操作的返回值解析与错误处理

在实际开发中,应根据业务场景选择合适的操作方法,并注意索引优化和文档大小限制,以确保数据库操作的性能和稳定性。

相关推荐
chehaoman2 小时前
MySQL的索引
android·数据库·mysql
cm6543202 小时前
用Python破解简单的替换密码
jvm·数据库·python
诗句藏于尽头2 小时前
基于GPT2的底模微调实现微信聊天风格模仿输出
学习·微信
%小农2 小时前
学习cursor
学习
还是做不到嘛\.2 小时前
DVWA靶场-Brute Force
运维·服务器·数据库·学习
老张聊数据集成2 小时前
ETL是什么?一文讲清ETL和ELT的区别
数据库
Oueii3 小时前
掌握Python魔法方法(Magic Methods)
jvm·数据库·python
Elastic 中国社区官方博客3 小时前
现已正式发布: Elastic Cloud Hosted 上的托管 OTLP Endpoint
大数据·运维·数据库·功能测试·elasticsearch·全文检索