MongoDB CRUD操作详解:数据的增删改查

写在前面:CRUD是数据库操作的核心,MongoDB提供了丰富的API来实现数据的增删改查。本篇将详细介绍MongoDB的各种CRUD操作,帮助您熟练掌握数据的基本操作技能。


文章目录

    • 一、插入文档
      • [1.1 insertOne - 插入单条文档](#1.1 insertOne - 插入单条文档)
      • [1.2 insertMany - 批量插入](#1.2 insertMany - 批量插入)
      • [1.3 insert - 通用插入](#1.3 insert - 通用插入)
      • [1.4 插入进阶](#1.4 插入进阶)
    • 二、查询文档
      • [2.1 find - 基本查询](#2.1 find - 基本查询)
      • [2.2 条件查询运算符](#2.2 条件查询运算符)
      • [2.3 逻辑运算符](#2.3 逻辑运算符)
      • [2.4 数组查询](#2.4 数组查询)
      • [2.5 嵌套文档查询](#2.5 嵌套文档查询)
    • 三、更新文档
      • [3.1 updateOne - 更新单条](#3.1 updateOne - 更新单条)
      • [3.2 updateMany - 批量更新](#3.2 updateMany - 批量更新)
      • [3.3 常用更新运算符](#3.3 常用更新运算符)
      • [3.4 upsert - 插入或更新](#3.4 upsert - 插入或更新)
    • 四、删除文档
      • [4.1 deleteOne - 删除单条](#4.1 deleteOne - 删除单条)
      • [4.2 deleteMany - 批量删除](#4.2 deleteMany - 批量删除)
      • [4.3 drop - 删除集合](#4.3 drop - 删除集合)
    • 五、投影与排序
      • [5.1 投影(Projection)](#5.1 投影(Projection))
      • [5.2 排序(Sort)](#5.2 排序(Sort))
      • [5.3 分页](#5.3 分页)
    • 六、实战案例:学生管理系统
      • [6.1 数据模型](#6.1 数据模型)
      • [6.2 常用查询](#6.2 常用查询)
      • [6.3 数据更新](#6.3 数据更新)
    • 七、原子性与事务
      • [7.1 原子性](#7.1 原子性)
      • [7.2 事务(Transaction)](#7.2 事务(Transaction))
    • 八、总结

一、插入文档

1.1 insertOne - 插入单条文档

javascript 复制代码
// 切换到数据库
use myapp

// 插入单条文档
db.users.insertOne({
    username: "zhangsan",
    email: "zhangsan@example.com",
    age: 25,
    city: "北京",
    tags: ["程序员", "摄影"],
    createdAt: new Date()
})

// 返回结果
{
    acknowledged: true,
    insertedId: ObjectId("507f1f77bcf86cd799439011")
}

1.2 insertMany - 批量插入

javascript 复制代码
// 插入多条文档
db.users.insertMany([
    {
        username: "lisi",
        email: "lisi@example.com",
        age: 28,
        city: "上海"
    },
    {
        username: "wangwu",
        email: "wangwu@example.com",
        age: 30,
        city: "深圳"
    },
    {
        username: "zhaoliu",
        email: "zhaoliu@example.com",
        age: 26,
        city: "广州"
    }
])

// 返回结果
{
    acknowledged: true,
    insertedIds: [
        ObjectId("..."),
        ObjectId("..."),
        ObjectId("...")
    ]
}

1.3 insert - 通用插入

javascript 复制代码
// insert可以插入单条或多条
db.products.insert({
    name: "iPhone 15",
    price: 5999,
    brand: "Apple"
})

db.orders.insert([
    {orderId: 1, total: 100},
    {orderId: 2, total: 200}
])

1.4 插入进阶

javascript 复制代码
// 插入带指定_id的文档
db.users.insertOne({
    _id: "user001",
    username: "admin",
    email: "admin@example.com"
})

// bulkWrite 批量操作
db.users.bulkWrite([
    { insertOne: { document: { name: "user1", age: 20 } } },
    { insertOne: { document: { name: "user2", age: 21 } } },
    { updateOne: {
        filter: { name: "zhangsan" },
        update: { $set: { age: 26 } }
    }},
    { deleteOne: {
        filter: { name: "lisi" }
    }}
])

二、查询文档

2.1 find - 基本查询

javascript 复制代码
// 查询users集合所有文档
db.users.find()

// 查询返回第一条
db.users.findOne()

// 指定条件查询
db.users.find({ city: "北京" })

// 查询并只返回指定字段
db.users.find(
    { city: "北京" },
    { username: 1, email: 1, _id: 0 }
)

// 排除某些字段
db.users.find(
    { age: { $gt: 25 } },
    { password: 0, salt: 0 }
)

2.2 条件查询运算符

javascript 复制代码
// 等于 $eq(默认就是等于)
db.users.find({ age: 25 })
db.users.find({ age: { $eq: 25 } })

// 不等于 $ne
db.users.find({ city: { $ne: "北京" } })

// 大于 $gt
db.users.find({ age: { $gt: 25 } })

// 大于等于 $gte
db.users.find({ age: { $gte: 25 } })

// 小于 $lt
db.users.find({ age: { $lt: 30 } })

// 小于等于 $lte
db.users.find({ age: { $lte: 30 } })

// 范围查询
db.users.find({ age: { $gte: 20, $lte: 30 } })

// in / not in
db.users.find({ city: { $in: ["北京", "上海", "深圳"] } })
db.users.find({ city: { $nin: ["北京", "上海"] } })

2.3 逻辑运算符

javascript 复制代码
// $and 多条件AND
db.users.find({
    $and: [
        { age: { $gt: 25 } },
        { city: "北京" }
    ]
})

// 简化写法(推荐)
db.users.find({ age: { $gt: 25 }, city: "北京" })

// $or 多条件OR
db.users.find({
    $or: [
        { city: "北京" },
        { city: "上海" }
    ]
})

// $not 取反
db.users.find({ age: { $not: { $gt: 25 } } })

// $nor 既不...也不...
db.users.find({
    $nor: [
        { city: "北京" },
        { status: "banned" }
    ]
})

2.4 数组查询

javascript 复制代码
// 插入带数组的文档
db.products.insertMany([
    { name: "手机", tags: ["电子产品", "数码", "通信"] },
    { name: "电脑", tags: ["电子产品", "数码", "办公"] },
    { name: "衣服", tags: ["服装", "穿戴"] }
])

// 数组包含 $all(所有元素都包含)
db.products.find({
    tags: { $all: ["电子产品", "数码"] }
})

// 数组包含任一 $in
db.products.find({
    tags: { $in: ["电子产品"] }
})

// 数组元素匹配 $elemMatch
db.scores.insertMany([
    { student: "张三", scores: [85, 92, 78] },
    { student: "李四", scores: [90, 88, 95] }
])

// 至少有 一个元素满足条件
db.scores.find({
    scores: { $elemMatch: { $gte: 90 } }
})

// 数组长度 $size
db.products.find({
    tags: { $size: 3 }
})

2.5 嵌套文档查询

javascript 复制代码
// 插入嵌套文档
db.orders.insertOne({
    orderId: "order001",
    customer: {
        name: "张三",
        phone: "13800138000",
        address: {
            city: "北京",
            district: "朝阳区"
        }
    },
    total: 299.99,
    items: [
        { product: "iPhone", quantity: 1, price: 299.99 }
    ]
})

// 查询嵌套字段(用点号)
db.orders.find({ "customer.name": "张三" })
db.orders.find({ "customer.address.city": "北京" })

三、更新文档

3.1 updateOne - 更新单条

javascript 复制代码
// 基本更新
db.users.updateOne(
    { username: "zhangsan" },  // 过滤条件
    { $set: { age: 26 } }       // 更新操作
)

// 返回结果
{
    acknowledged: true,
    matchedCount: 1,
    modifiedCount: 1,
    upsertedCount: 0
}

3.2 updateMany - 批量更新

javascript 复制代码
// 更新所有年龄大于25岁的用户
db.users.updateMany(
    { age: { $gt: 25 } },
    { $set: { status: "adult" } }
)

// 返回结果
{
    acknowledged: true,
    matchedCount: 5,
    modifiedCount: 5,
    upsertedCount: 0
}

3.3 常用更新运算符

javascript 复制代码
// $set - 设置字段值
db.users.updateOne(
    { _id: ObjectId("...") },
    { $set: { email: "new@example.com", age: 27 } }
)

// $unset - 删除字段
db.users.updateOne(
    { _id: ObjectId("...") },
    { $unset: { tempField: "" } }
)

// $inc - 递增/递减
db.products.updateOne(
    { name: "iPhone" },
    { $inc: { stock: -1, sold: 1 } }
)

// $mul - 乘运算
db.orders.updateMany(
    {},
    { $mul: { total: 1.1 } }  // 所有订单增加10%
)

// $rename - 重命名字段
db.users.updateMany(
    {},
    { $rename: { "username": "name" } }
)

// $setOnInsert - 插入时设置
db.users.updateOne(
    { email: "new@example.com" },
    { 
        $set: { status: "active" },
        $setOnInsert: { createdAt: new Date() }
    },
    { upsert: true }
)

// $push - 添加数组元素
db.users.updateOne(
    { _id: ObjectId("...") },
    { $push: { tags: "新标签" } }
)

// $pull - 移除数组元素
db.users.updateOne(
    { _id: ObjectId("...") },
    { $pull: { tags: "旧标签" } }
)

// $addToSet - 不重复添加
db.users.updateOne(
    { _id: ObjectId("...") },
    { $addToSet: { tags: "VIP" } }
)

3.4 upsert - 插入或更新

javascript 复制代码
// 如果不存在则插入,存在则更新
db.users.updateOne(
    { username: "newuser" },
    { $set: { email: "new@example.com", age: 25 } },
    { upsert: true }
)

四、删除文档

4.1 deleteOne - 删除单条

javascript 复制代码
// 删除单条
db.users.deleteOne({ _id: ObjectId("507f1f77bcf86cd799439011") })

// 删除第一条匹配的文章
db.articles.deleteOne({ status: "draft" })

// 返回结果
{ acknowledged: true, deletedCount: 1 }

4.2 deleteMany - 批量删除

javascript 复制代码
// 删除所有status为banned的用户
db.users.deleteMany({ status: "banned" })

// 删除所有年龄小于18岁的用户
db.users.deleteMany({ age: { $lt: 18 } })

// 删除集合所有文档(慎用!)
db.users.deleteMany({})

4.3 drop - 删除集合

javascript 复制代码
// 删除整个集合(包括索引)
db.users.drop()

// 删除数据库
db.dropDatabase()

五、投影与排序

5.1 投影(Projection)

javascript 复制代码
// 只返回指定字段
db.users.find(
    {},  // 查询条件
    { username: 1, email: 1, _id: 0 }  // 1表示显示,0表示不显示
)

// 排除敏感字段
db.users.find(
    {},
    { password: 0, salt: 0, token: 0 }
)

// 包含计算字段
db.orders.find(
    {},
    {
        orderId: 1,
        total: 1,
        finalTotal: { $multiply: ["$total", 0.9] }  // 9折价格
    }
)

5.2 排序(Sort)

javascript 复制代码
// 按年龄升序
db.users.find().sort({ age: 1 })

// 按年龄降序
db.users.find().sort({ age: -1 })

// 多字段排序:先按城市升序,再按年龄降序
db.users.find().sort({ city: 1, age: -1 })

5.3 分页

javascript 复制代码
// 跳过前10条,取5条(第二页)
db.users.find().skip(10).limit(5)

// 分页查询示例
db.users.find()
    .sort({ createdAt: -1 })
    .skip((page - 1) * pageSize)
    .limit(pageSize)

六、实战案例:学生管理系统

6.1 数据模型

javascript 复制代码
// 学生集合
db.students.insertMany([
    {
        studentId: "S001",
        name: "张三",
        age: 18,
        gender: "男",
        class: "计算机2201",
        scores: [
            { subject: "数学", score: 85 },
            { subject: "英语", score: 92 },
            { subject: "编程", score: 88 }
        ],
        status: "在读"
    },
    {
        studentId: "S002",
        name: "李四",
        age: 19,
        gender: "女",
        class: "计算机2201",
        scores: [
            { subject: "数学", score: 90 },
            { subject: "英语", score: 88 },
            { subject: "编程", score: 95 }
        ],
        status: "在读"
    }
])

6.2 常用查询

javascript 复制代码
// 1. 查询计算机2201班所有学生
db.students.find({ class: "计算机2201" })

// 2. 查询年龄大于18岁的学生
db.students.find({ age: { $gt: 18 } })

// 3. 查询数学成绩大于90分的学生
db.students.find({
    scores: { $elemMatch: { subject: "数学", score: { $gt: 90 } } }
})

// 4. 查询在读学生,按年龄升序
db.students.find({ status: "在读" }).sort({ age: 1 })

// 5. 分页查询:每页10条
db.students.find().limit(10)

6.3 数据更新

javascript 复制代码
// 1. 更新学生年龄
db.students.updateOne(
    { studentId: "S001" },
    { $set: { age: 19 } }
)

// 2. 添加一门成绩
db.students.updateOne(
    { studentId: "S001" },
    { $push: { scores: { subject: "数据库", score: 87 } } }
)

// 3. 修改某门课程成绩
db.students.updateOne(
    { 
        studentId: "S001",
        "scores.subject": "数学"
    },
    { 
        $set: { "scores.$.score": 90 }
    }
)

// 4. 删除退学学生
db.students.deleteMany({ status: "退学" })

七、原子性与事务

7.1 原子性

复制代码
⚡ MongoDB原子性特点:

MongoDB的写操作是原子性的:
- 单个文档的写操作是原子性的
- 多文档操作不是原子的(需要事务)

示例:
db.accounts.updateOne(
    { _id: 1, balance: { $gte: 100 } },
    { $inc: { balance: -100 } }
)
// 这两个操作是原子的:检查余额 >= 100 并扣款

7.2 事务(Transaction)

javascript 复制代码
// 开启事务会话
const session = db.getMongo().startSession();

session.startTransaction({
    readConcern: { level: "snapshot" },
    writeConcern: { w: "majority" }
});

try {
    // 操作1:从账户A扣款
    session.getDatabase("bank").accounts.updateOne(
        { _id: "A", balance: { $gte: 100 } },
        { $inc: { balance: -100 } }
    );

    // 操作2:向账户B存款
    session.getDatabase("bank").accounts.updateOne(
        { _id: "B" },
        { $inc: { balance: 100 } },
        { upsert: true }
    );

    // 提交事务
    session.commitTransaction();
} catch (error) {
    // 回滚事务
    session.abortTransaction();
    throw error;
} finally {
    session.endSession();
}

八、总结

复制代码
📊 本篇总结:

✅ 掌握内容:
- 插入文档:insertOne、insertMany、bulkWrite
- 查询文档:条件查询、逻辑运算、数组查询、嵌套查询
- 更新文档:updateOne、updateMany、各种更新运算符
- 删除文档:deleteOne、deleteMany、drop
- 投影排序:字段选择、排序、分页
- 原子性与事务

作者 :刘~浪地球
更新时间 :2026-05-08
本文声明:原创不易,转载需授权!

相关推荐
铁皮哥1 小时前
【后端开发】RabbitMQ、RocketMQ、Kafka 怎么选?我从业务场景重新梳理了一遍
java·linux·数据库·分布式·kafka·rabbitmq·rocketmq
2301_795099741 小时前
如何在MongoDB主从架构中利用Change Stream捕获数据变更_必须在副本集模式下工作
jvm·数据库·python
AC赳赳老秦1 小时前
数据库操作自动化:用 OpenClaw 对接 Navicat/DBeaver,实现数据备份、脱敏、日常操作自动化
java·运维·数据库·python·oracle·自动化·openclaw
程序员小白条1 小时前
AI 编程辅助,从入门到真香
java·开发语言·数据库·人工智能·面试·职场和发展
2401_880071401 小时前
Django怎么优雅发送邮件_Python配置SMTP后端实现异步通知
jvm·数据库·python
m0_463672201 小时前
如何快速检索SQL中的隐藏字符_使用转义与函数处理
jvm·数据库·python
u0110225121 小时前
怎么优化MongoDB的软删除设计_布尔标记与删除时间戳
jvm·数据库·python
老纪1 小时前
JavaScript中BigInt与Number类型混用的报错机制
jvm·数据库·python
档案宝档案管理1 小时前
全文检索 vs 条件检索 vs 目录检索:适用场景对比
大数据·数据库·全文检索