MongoDB基础知识

MongoDB基础知识

目录

基础篇

一、MongoDB入门指南(零基础必读)

1.1 MongoDB是什么?

把MongoDB想象成一个超级大的Excel表格本:

  • 数据库(Database)就像一个Excel工作簿
  • 集合(Collection)就像工作簿中的工作表
  • 文档(Document)就像工作表中的一行数据
  • 字段(Field)就像表格中的列

与传统MySQL数据库相比:

  • MySQL要求表格结构固定(每列的类型必须一致)
  • MongoDB更灵活,同一个集合中的文档可以有不同的字段

1.2 为什么选择MongoDB?

  1. 容易上手

    • 数据格式类似JSON,对开发者友好
    • 不需要设计复杂的表关系
    • 存储格式灵活,想存什么就存什么
  2. 适合的应用场景

    • 存储网站用户数据
    • 存储商品评论信息
    • 记录系统日志
    • 存储游戏数据

1.3 基础操作入门示例

1. 数据库操作
javascript 复制代码
// 创建/切换到"我的数据库"
use mydb

// 查看有哪些数据库
show dbs

// 删除当前使用的数据库
db.dropDatabase()
2. 集合操作
javascript 复制代码
// 创建"用户信息"集合
db.createCollection("用户信息")

// 查看所有集合
show collections

// 删除"用户信息"集合
db.用户信息.drop()
3. 实用操作示例
添加用户信息
javascript 复制代码
// 添加一个用户
db.用户信息.insertOne({
    姓名: "小明",
    年龄: 18,
    爱好: ["打游戏", "看电影"],
    联系方式: {
        手机: "13812345678",
        邮箱: "[email protected]"
    }
})
查询用户信息
javascript 复制代码
// 查找所有用户
db.用户信息.find()

// 查找叫"小明"的用户
db.用户信息.find({姓名: "小明"})

// 查找18岁的用户
db.用户信息.find({年龄: 18})

// 查找大于18岁的用户
db.用户信息.find({年龄: {$gt: 18}})

1.4 新手常见问题解决

1. 数据重复问题
javascript 复制代码
// 设置用户名不能重复
db.users.createIndex({用户名: 1}, {unique: true})

// 检查用户名是否存在
const userExists = db.users.findOne({用户名: "xiaoming"})
if (!userExists) {
    // 可以注册
}
2. 查询速度慢问题
javascript 复制代码
// 为常用查询字段创建索引
db.users.createIndex({年龄: 1})
db.users.createIndex({注册时间: 1})

// 只返回需要的字段
db.users.find(
    {年龄: {$gt: 18}},
    {用户名: 1, 年龄: 1, _id: 0}
)

1.5 新手使用建议

  1. 命名建议

    • 数据库名用小写字母
    • 集合名用有意义的名字(如users、products)
    • 字段名用简单易懂的名字
  2. 数据组织建议

    • 相关的数据尽量放在一起
    • 避免过深的数据嵌套
    • 数组中不要存太多数据
  3. 查询建议

    • 常用查询字段要加索引
    • 查询时只获取需要的字段
    • 避免一次查询太多数据
  4. 实用技巧

    • 使用复合查询减少查询次数
    • 使用批量操作提高效率
    • 定期备份重要数据

二、MongoDB简介

2.1 什么是MongoDB?

MongoDB是一个开源的文档型数据库,具有以下特点:

  • 高性能、高可用性、易扩展
  • 支持动态查询
  • 支持索引
  • 支持复制和分片
  • 支持多种编程语言

2.2 基本概念

  1. 数据库(Database)

    • MongoDB中的数据库是一个集合的容器
    • 每个数据库都有独立的权限控制
  2. 集合(Collection)

    • 类似于关系型数据库中的表
    • 不需要预先定义结构
    • 可以包含不同结构的文档
  3. 文档(Document)

    • 类似于关系型数据库中的行
    • 使用BSON格式(JSON的二进制形式)
    • 可以包含不同类型的字段
  4. 字段(Field)

    • 文档中的键值对
    • 支持多种数据类型
    • 可以嵌套和数组

三、MongoDB安装与配置

3.1 安装MongoDB

bash 复制代码
# Windows安装
# 1. 下载MongoDB安装包
# 2. 运行安装程序
# 3. 配置环境变量

# Linux安装
sudo apt-get update
sudo apt-get install -y mongodb

# Mac安装
brew tap mongodb/brew
brew install mongodb-community

3.2 启动MongoDB

bash 复制代码
# Windows启动
net start MongoDB

# Linux启动
sudo systemctl start mongodb

# Mac启动
brew services start mongodb-community

3.3 连接MongoDB

bash 复制代码
# 命令行连接
mongosh

# 指定主机和端口连接
mongosh --host localhost --port 27017

# 使用用户名密码连接
mongosh --username admin --password password

四、MongoDB基本操作

4.1 数据库操作

javascript 复制代码
// 创建/切换数据库
use mydb

// 查看所有数据库
show dbs

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

// 查看当前数据库
db

4.2 集合操作

javascript 复制代码
// 创建集合
db.createCollection("users")

// 查看所有集合
show collections

// 删除集合
db.users.drop()

// 查看集合统计信息
db.users.stats()

4.3 文档操作

javascript 复制代码
// 插入单个文档
db.users.insertOne({
    name: "张三",
    age: 25,
    email: "[email protected]",
    hobbies: ["读书", "运动"],
    address: {
        city: "北京",
        street: "朝阳区"
    }
})

// 插入多个文档
db.users.insertMany([
    {
        name: "李四",
        age: 30,
        email: "[email protected]"
    },
    {
        name: "王五",
        age: 28,
        email: "[email protected]"
    }
])

// 查询文档
db.users.find()

// 条件查询
db.users.find({ age: { $gt: 25 } })

// 更新文档
db.users.updateOne(
    { name: "张三" },
    { $set: { age: 26 } }
)

// 删除文档
db.users.deleteOne({ name: "张三" })

五、MongoDB查询操作

5.1 基础查询

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

// 条件查询
db.users.find({ age: 25 })

// 比较操作符
db.users.find({ age: { $gt: 25 } })  // 大于
db.users.find({ age: { $lt: 25 } })  // 小于
db.users.find({ age: { $gte: 25 } }) // 大于等于
db.users.find({ age: { $lte: 25 } }) // 小于等于
db.users.find({ age: { $ne: 25 } })  // 不等于

// 逻辑操作符
db.users.find({ $or: [{ age: 25 }, { age: 30 }] })  // OR
db.users.find({ $and: [{ age: 25 }, { name: "张三" }] })  // AND
db.users.find({ age: { $not: { $gt: 25 } } })  // NOT

// 限制返回字段
db.users.find({}, { name: 1, age: 1, _id: 0 })

// 排序
db.users.find().sort({ age: 1 })  // 升序
db.users.find().sort({ age: -1 }) // 降序

// 分页
db.users.find().skip(10).limit(5)

5.2 高级查询

javascript 复制代码
// 正则表达式查询
db.users.find({ name: /^张/ })

// 数组查询
db.users.find({ hobbies: "读书" })
db.users.find({ hobbies: { $all: ["读书", "运动"] } })
db.users.find({ hobbies: { $size: 2 } })

// 嵌套文档查询
db.users.find({ "address.city": "北京" })

// 聚合查询
db.users.aggregate([
    { $group: { _id: "$age", count: { $sum: 1 } } },
    { $sort: { count: -1 } }
])

进阶篇

六、MongoDB索引

6.1 索引操作

javascript 复制代码
// 创建索引
db.users.createIndex({ email: 1 })

// 创建唯一索引
db.users.createIndex({ email: 1 }, { unique: true })

// 创建复合索引
db.users.createIndex({ name: 1, age: -1 })

// 查看索引
db.users.getIndexes()

// 删除索引
db.users.dropIndex({ email: 1 })

6.2 索引类型

  • 单字段索引
  • 复合索引
  • 多键索引
  • 文本索引
  • 地理空间索引
  • 哈希索引

七、MongoDB聚合操作

7.1 聚合管道

javascript 复制代码
// 基本聚合
db.users.aggregate([
    { $match: { age: { $gt: 25 } } },
    { $group: { _id: "$age", count: { $sum: 1 } } },
    { $sort: { count: -1 } }
])

// 复杂聚合
db.orders.aggregate([
    { $match: { status: "completed" } },
    { $group: {
        _id: "$customer_id",
        total: { $sum: "$amount" },
        count: { $sum: 1 }
    }},
    { $lookup: {
        from: "customers",
        localField: "_id",
        foreignField: "_id",
        as: "customer"
    }},
    { $unwind: "$customer" },
    { $project: {
        customer_name: "$customer.name",
        total: 1,
        count: 1
    }}
])

7.2 聚合操作符

  • $match:过滤文档
  • $group:分组
  • $sort:排序
  • $limit:限制
  • $skip:跳过
  • $project:投影
  • $lookup:关联查询
  • $unwind:展开数组

八、MongoDB数据模型

8.1 文档模型

javascript 复制代码
// 嵌入式文档
{
    _id: ObjectId("..."),
    name: "张三",
    orders: [
        {
            order_id: "001",
            amount: 100,
            items: [
                { product: "手机", quantity: 1 },
                { product: "耳机", quantity: 2 }
            ]
        }
    ]
}

// 引用式文档
{
    _id: ObjectId("..."),
    name: "张三",
    order_ids: [
        ObjectId("..."),
        ObjectId("...")
    ]
}

8.2 数据关系

  • 一对一关系
  • 一对多关系
  • 多对多关系

九、MongoDB安全

9.1 用户管理

javascript 复制代码
// 创建用户
db.createUser({
    user: "admin",
    pwd: "password",
    roles: ["userAdminAnyDatabase"]
})

// 修改用户
db.updateUser("admin", {
    roles: ["userAdminAnyDatabase", "readWriteAnyDatabase"]
})

// 删除用户
db.dropUser("admin")

9.2 访问控制

javascript 复制代码
// 启用认证
security:
  authorization: enabled

// 设置访问权限
db.grantRolesToUser("user", ["readWrite"])

十、MongoDB备份恢复

10.1 备份操作

bash 复制代码
# 备份整个数据库
mongodump --db mydb --out /backup

# 备份特定集合
mongodump --db mydb --collection users --out /backup

# 压缩备份
mongodump --db mydb --gzip --archive=/backup/backup.gz

10.2 恢复操作

bash 复制代码
# 恢复整个数据库
mongorestore --db mydb /backup/mydb

# 恢复特定集合
mongorestore --db mydb --collection users /backup/mydb/users.bson

# 恢复压缩备份
mongorestore --gzip --archive=/backup/backup.gz

十一、MongoDB性能优化

11.1 查询优化

  • 使用索引
  • 限制返回字段
  • 使用投影
  • 使用分页
  • 避免使用正则表达式

11.2 索引优化

  • 创建合适的索引
  • 避免过多索引
  • 使用复合索引
  • 定期维护索引

11.3 配置优化

yaml 复制代码
# mongod.conf
storage:
  wiredTiger:
    engineConfig:
      cacheSizeGB: 4
    collectionConfig:
      blockCompressor: snappy

operationProfiling:
  mode: slowOp
  slowOpThresholdMs: 100

replication:
  oplogSizeMB: 10240

十二、MongoDB高级特性

12.1 Change Streams

javascript 复制代码
// 监听集合变化
const changeStream = db.collection('users').watch();
changeStream.on('change', (change) => {
    console.log('检测到变化:', change);
});

// 使用管道过滤器
const pipeline = [
    { $match: { 'operationType': 'insert' } }
];
const filteredStream = db.collection('users').watch(pipeline);

12.2 事务处理

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

try {
    // 转账操作示例
    db.accounts.updateOne(
        { userId: "user1" },
        { $inc: { balance: -100 } },
        { session }
    );
    
    db.accounts.updateOne(
        { userId: "user2" },
        { $inc: { balance: 100 } },
        { session }
    );
    
    await session.commitTransaction();
} catch (error) {
    await session.abortTransaction();
    throw error;
} finally {
    session.endSession();
}

12.3 GridFS文件存储

javascript 复制代码
// 存储大文件
const bucket = new GridFSBucket(db);
fs.createReadStream('video.mp4')
  .pipe(bucket.openUploadStream('video.mp4'));

// 读取文件
bucket.openDownloadStreamByName('video.mp4')
  .pipe(fs.createWriteStream('downloaded-video.mp4'));

十三、MongoDB复制集

13.1 复制集配置

yaml 复制代码
# mongod.conf
replication:
  replSetName: "myReplicaSet"
javascript 复制代码
// 初始化复制集
rs.initiate({
    _id: "myReplicaSet",
    members: [
        { _id: 0, host: "mongodb1:27017" },
        { _id: 1, host: "mongodb2:27017" },
        { _id: 2, host: "mongodb3:27017" }
    ]
});

// 查看复制集状态
rs.status();

// 添加节点
rs.add("mongodb4:27017");

// 移除节点
rs.remove("mongodb4:27017");

13.2 复制集运维

javascript 复制代码
// 主节点降级
rs.stepDown();

// 设置优先级
cfg = rs.conf();
cfg.members[0].priority = 2;
rs.reconfig(cfg);

// 设置隐藏节点
cfg.members[2].hidden = true;
cfg.members[2].priority = 0;
rs.reconfig(cfg);

十四、MongoDB分片集群

14.1 分片集群架构

  • Config Server(配置服务器)
  • Shard Server(分片服务器)
  • Mongos Router(路由服务器)

14.2 分片配置

javascript 复制代码
// 启用分片
sh.enableSharding("mydb");

// 对集合进行分片
sh.shardCollection("mydb.users", { userId: "hashed" });

// 范围分片
sh.shardCollection("mydb.orders", { orderDate: 1 });

// 复合分片键
sh.shardCollection("mydb.products", { category: 1, price: 1 });

应用篇

十五、MongoDB性能诊断

15.1 查询分析

javascript 复制代码
// 执行计划分析
db.users.find({ age: { $gt: 25 } }).explain("executionStats");

// 慢查询分析
db.setProfilingLevel(1, { slowms: 100 });
db.system.profile.find().sort({ ts: -1 });

// 查询统计
db.users.aggregate([
    { $indexStats: {} }
]);

15.2 性能监控

javascript 复制代码
// 服务器状态
db.serverStatus();

// 数据库统计
db.stats();

// 集合统计
db.users.stats();

// 连接情况
db.currentOp();

十六、MongoDB数据迁移

16.1 数据导出

bash 复制代码
# 导出JSON格式
mongoexport --db mydb --collection users --out users.json

# 导出CSV格式
mongoexport --db mydb --collection users --type=csv --fields name,age,email --out users.csv

# 条件导出
mongoexport --db mydb --collection users --query '{"age":{"$gt":25}}' --out users_filtered.json

16.2 数据导入

bash 复制代码
# 导入JSON
mongoimport --db mydb --collection users --file users.json

# 导入CSV
mongoimport --db mydb --collection users --type csv --headerline --file users.csv

# 导入时进行转换
mongoimport --db mydb --collection users --file users.json --transform 'this.age = Number(this.age)'

十七、MongoDB应用开发最佳实践

17.1 数据建模

javascript 复制代码
// 反范式设计示例
{
    _id: ObjectId("..."),
    orderId: "ORD001",
    customer: {
        name: "张三",
        email: "[email protected]",
        address: "北京市朝阳区"
    },
    items: [
        {
            productId: "P001",
            name: "iPhone",
            price: 6999,
            quantity: 1
        }
    ],
    totalAmount: 6999,
    status: "completed"
}

17.2 查询优化技巧

javascript 复制代码
// 使用覆盖索引
db.users.find(
    { age: { $gt: 25 } },
    { _id: 0, name: 1, age: 1 }
).hint({ age: 1, name: 1 });

// 使用投影减少网络传输
db.users.find(
    { },
    { name: 1, age: 1, _id: 0 }
);

// 批量操作
db.users.bulkWrite([
    { insertOne: { document: { name: "张三", age: 25 } } },
    { updateOne: { 
        filter: { name: "李四" },
        update: { $set: { age: 26 } }
    } },
    { deleteOne: { filter: { name: "王五" } } }
]);

17.3 错误处理

javascript 复制代码
try {
    // 插入唯一索引冲突处理
    await db.users.insertOne({
        email: "[email protected]",
        name: "张三"
    });
} catch (error) {
    if (error.code === 11000) {
        console.log('邮箱已存在');
    } else {
        throw error;
    }
}

十八、MongoDB运维管理

18.1 日志管理

yaml 复制代码
# mongod.conf
systemLog:
  destination: file
  path: "/var/log/mongodb/mongod.log"
  logAppend: true
  logRotate: rename

18.2 监控告警

javascript 复制代码
// 设置告警阈值
db.createCollection("alerts");
db.alerts.createIndex({ "timestamp": 1 }, { expireAfterSeconds: 86400 });

// 监控连接数
const connections = db.serverStatus().connections;
if (connections.current > connections.available * 0.8) {
    db.alerts.insertOne({
        type: "connection_warning",
        message: "连接数超过80%",
        timestamp: new Date()
    });
}

18.3 容量规划

  • 评估数据增长率
  • 监控磁盘使用情况
  • 规划扩容时机
  • 制定备份策略

十九、MongoDB常见应用场景示例

19.1 用户管理系统

javascript 复制代码
// 用户注册
db.users.insertOne({
    用户名: "xiaoming",
    密码: "123456",  // 实际应用中要加密
    注册时间: new Date(),
    最后登录: new Date(),
    状态: "正常"
})

// 用户登录验证
db.users.findOne({
    用户名: "xiaoming",
    密码: "123456"
})

// 更新登录时间
db.users.updateOne(
    {用户名: "xiaoming"},
    {$set: {最后登录: new Date()}}
)

19.2 商品评论系统

javascript 复制代码
// 添加评论
db.comments.insertOne({
    商品ID: "prod123",
    用户名: "xiaoming",
    评分: 5,
    内容: "很好用!",
    评论时间: new Date(),
    点赞数: 0
})

// 查看商品评论
db.comments.find({商品ID: "prod123"})

// 给评论点赞
db.comments.updateOne(
    {_id: "评论ID"},
    {$inc: {点赞数: 1}}  // $inc表示增加
)

19.3 内容管理系统

javascript 复制代码
// 创建文章
db.articles.insertOne({
    标题: "MongoDB入门指南",
    作者: "xiaoming",
    内容: "MongoDB是一个文档型数据库...",
    标签: ["数据库", "NoSQL", "MongoDB"],
    创建时间: new Date(),
    更新时间: new Date(),
    阅读量: 0,
    点赞数: 0
})

// 更新文章
db.articles.updateOne(
    {标题: "MongoDB入门指南"},
    {
        $set: {更新时间: new Date()},
        $inc: {阅读量: 1}
    }
)

// 按标签查询文章
db.articles.find({标签: "MongoDB"})

19.4 日志系统

javascript 复制代码
// 记录系统日志
db.logs.insertOne({
    级别: "ERROR",
    模块: "用户认证",
    消息: "用户登录失败",
    详情: "密码错误",
    时间: new Date(),
    用户ID: "user123",
    IP地址: "192.168.1.1"
})

// 查询错误日志
db.logs.find({级别: "ERROR"})

// 按时间范围查询
db.logs.find({
    时间: {
        $gte: new Date(new Date().setDate(new Date().getDate() - 7)),
        $lte: new Date()
    }
})

二十、MongoDB与Java集成

20.1 MongoDB Java驱动

java 复制代码
// 添加MongoDB Java驱动依赖
// Maven
<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongodb-driver-sync</artifactId>
    <version>4.11.1</version>
</dependency>

// Gradle
implementation 'org.mongodb:mongodb-driver-sync:4.11.1'

20.2 连接MongoDB

java 复制代码
// 创建MongoDB客户端
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");

// 获取数据库
MongoDatabase database = mongoClient.getDatabase("mydb");

// 获取集合
MongoCollection<Document> collection = database.getCollection("users");

// 关闭连接
mongoClient.close();

20.3 基本操作示例

java 复制代码
// 插入文档
Document document = new Document("name", "张三")
    .append("age", 25)
    .append("email", "[email protected]");
collection.insertOne(document);

// 查询文档
Document query = new Document("name", "张三");
Document result = collection.find(query).first();
System.out.println(result.toJson());

// 更新文档
Document updateQuery = new Document("name", "张三");
Document update = new Document("$set", new Document("age", 26));
collection.updateOne(updateQuery, update);

// 删除文档
Document deleteQuery = new Document("name", "张三");
collection.deleteOne(deleteQuery);

20.4 使用MongoDB Java驱动的高级功能

java 复制代码
// 批量操作
List<WriteModel<Document>> writes = new ArrayList<>();
writes.add(new InsertOneModel<>(new Document("name", "李四").append("age", 30)));
writes.add(new UpdateOneModel<>(
    new Document("name", "王五"),
    new Document("$set", new Document("age", 28))
));
writes.add(new DeleteOneModel<>(new Document("name", "赵六")));

BulkWriteResult bulkWriteResult = collection.bulkWrite(writes);
System.out.println("插入: " + bulkWriteResult.getInsertedCount());
System.out.println("更新: " + bulkWriteResult.getModifiedCount());
System.out.println("删除: " + bulkWriteResult.getDeletedCount());

// 聚合操作
List<Document> pipeline = Arrays.asList(
    new Document("$match", new Document("age", new Document("$gt", 25))),
    new Document("$group", new Document("_id", "$age")
        .append("count", new Document("$sum", 1))),
    new Document("$sort", new Document("count", -1))
);

MongoCursor<Document> cursor = collection.aggregate(pipeline).iterator();
while (cursor.hasNext()) {
    System.out.println(cursor.next().toJson());
}

二十一、MongoDB与Spring Boot集成

21.1 添加Spring Data MongoDB依赖

xml 复制代码
<!-- Maven -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

<!-- Gradle -->
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'

21.2 配置MongoDB连接

yaml 复制代码
# application.yml
spring:
  data:
    mongodb:
      uri: mongodb://localhost:27017/mydb
      # 或者使用以下配置
      # host: localhost
      # port: 27017
      # database: mydb
      # username: admin
      # password: password

21.3 创建实体类

java 复制代码
@Document(collection = "users")
public class User {
    @Id
    private String id;
    
    private String name;
    private int age;
    private String email;
    private List<String> hobbies;
    private Address address;
    
    // 构造函数、getter和setter方法
    
    // 内部类
    public static class Address {
        private String city;
        private String street;
        
        // 构造函数、getter和setter方法
    }
}

21.4 创建Repository接口

java 复制代码
@Repository
public interface UserRepository extends MongoRepository<User, String> {
    // 自定义查询方法
    List<User> findByAgeGreaterThan(int age);
    List<User> findByNameStartingWith(String prefix);
    Optional<User> findByEmail(String email);
    
    // 使用@Query注解自定义查询
    @Query("{ 'age' : { $gt : ?0, $lt : ?1 } }")
    List<User> findByAgeBetween(int minAge, int maxAge);
}

21.5 使用MongoDB Template

java 复制代码
@Service
public class UserService {
    @Autowired
    private MongoTemplate mongoTemplate;
    
    public List<User> findUsersByAge(int age) {
        Query query = new Query(Criteria.where("age").gt(age));
        return mongoTemplate.find(query, User.class);
    }
    
    public void updateUserAge(String id, int newAge) {
        Query query = new Query(Criteria.where("id").is(id));
        Update update = new Update().set("age", newAge);
        mongoTemplate.updateFirst(query, update, User.class);
    }
    
    public List<User> aggregateUsersByAge() {
        Aggregation aggregation = Aggregation.newAggregation(
            Aggregation.match(Criteria.where("age").gt(25)),
            Aggregation.group("age").count().as("count"),
            Aggregation.sort(Sort.Direction.DESC, "count")
        );
        
        AggregationResults<User> results = mongoTemplate.aggregate(
            aggregation, "users", User.class);
        return results.getMappedResults();
    }
}

二十二、MongoDB与Docker部署

22.1 使用Docker运行MongoDB

bash 复制代码
# 拉取MongoDB镜像
docker pull mongo:latest

# 运行MongoDB容器
docker run -d --name mongodb -p 27017:27017 mongo:latest

# 运行MongoDB容器(带数据持久化)
docker run -d --name mongodb -p 27017:27017 -v /data/mongodb:/data/db mongo:latest

# 运行MongoDB容器(带认证)
docker run -d --name mongodb -p 27017:27017 -e MONGO_INITDB_ROOT_USERNAME=admin -e MONGO_INITDB_ROOT_PASSWORD=password mongo:latest

22.2 使用Docker Compose部署MongoDB

yaml 复制代码
# docker-compose.yml
version: '3'
services:
  mongodb:
    image: mongo:latest
    container_name: mongodb
    ports:
      - "27017:27017"
    volumes:
      - ./data:/data/db
    environment:
      - MONGO_INITDB_ROOT_USERNAME=admin
      - MONGO_INITDB_ROOT_PASSWORD=password
    networks:
      - mongo-network

  mongo-express:
    image: mongo-express:latest
    container_name: mongo-express
    ports:
      - "8081:8081"
    environment:
      - ME_CONFIG_MONGODB_ADMINUSERNAME=admin
      - ME_CONFIG_MONGODB_ADMINPASSWORD=password
      - ME_CONFIG_MONGODB_URL=mongodb://admin:password@mongodb:27017/
    depends_on:
      - mongodb
    networks:
      - mongo-network

networks:
  mongo-network:
    driver: bridge

22.3 使用Docker部署MongoDB复制集

yaml 复制代码
# docker-compose-replica.yml
version: '3'
services:
  mongodb1:
    image: mongo:latest
    container_name: mongodb1
    command: mongod --replSet rs0 --bind_ip_all
    ports:
      - "27017:27017"
    volumes:
      - ./data1:/data/db
    networks:
      - mongo-network

  mongodb2:
    image: mongo:latest
    container_name: mongodb2
    command: mongod --replSet rs0 --bind_ip_all
    ports:
      - "27018:27017"
    volumes:
      - ./data2:/data/db
    networks:
      - mongo-network

  mongodb3:
    image: mongo:latest
    container_name: mongodb3
    command: mongod --replSet rs0 --bind_ip_all
    ports:
      - "27019:27017"
    volumes:
      - ./data3:/data/db
    networks:
      - mongo-network

networks:
  mongo-network:
    driver: bridge
bash 复制代码
# 初始化复制集
docker exec -it mongodb1 mongosh --eval "rs.initiate({
  _id: 'rs0',
  members: [
    {_id: 0, host: 'mongodb1:27017'},
    {_id: 1, host: 'mongodb2:27017'},
    {_id: 2, host: 'mongodb3:27017'}
  ]
})"

最佳实践篇

二十三、MongoDB常见问题解答

23.1 连接问题

问题 : 无法连接到MongoDB服务器
解决方案:

  1. 检查MongoDB服务是否正在运行
  2. 检查防火墙设置,确保端口27017开放
  3. 检查MongoDB配置文件中的bindIp设置
  4. 如果使用认证,确保用户名和密码正确

23.2 性能问题

问题 : MongoDB查询速度慢
解决方案:

  1. 为常用查询字段创建索引
  2. 使用explain()分析查询执行计划
  3. 优化查询,只返回需要的字段
  4. 检查服务器资源使用情况(CPU、内存、磁盘I/O)
  5. 考虑增加服务器资源或使用分片集群

23.3 数据一致性问题

问题 : 在复制集中出现数据不一致
解决方案:

  1. 检查复制集状态:rs.status()
  2. 检查主节点和从节点的数据差异
  3. 如果从节点落后太多,考虑重新同步
  4. 确保网络连接稳定,避免网络分区

23.4 内存问题

问题 : MongoDB占用过多内存
解决方案:

  1. 调整WiredTiger缓存大小
  2. 监控内存使用情况
  3. 考虑增加服务器内存
  4. 优化查询和索引,减少内存使用

23.5 磁盘空间问题

问题 : MongoDB磁盘空间不足
解决方案:

  1. 清理不需要的数据
  2. 压缩集合:db.runCommand({compact: "collection_name"})
  3. 增加磁盘空间
  4. 考虑使用分片集群分散数据

二十四、MongoDB最佳实践总结

24.1 数据建模最佳实践

  1. 嵌入vs引用

    • 一对少关系:使用嵌入
    • 一对多关系:根据查询模式决定
    • 多对多关系:通常使用引用
  2. 文档大小

    • 保持文档大小在16MB以下
    • 避免过深的嵌套(不超过3-4层)
    • 避免过大的数组
  3. 字段命名

    • 使用简短但有意义的字段名
    • 保持命名风格一致
    • 避免使用特殊字符

24.2 查询优化最佳实践

  1. 索引策略

    • 为所有查询创建适当的索引
    • 避免过多索引(每个集合不超过64个)
    • 使用复合索引支持多字段查询
    • 考虑索引顺序(等值查询字段放在前面)
  2. 查询模式

    • 使用覆盖索引减少内存使用
    • 使用投影只返回需要的字段
    • 使用批量操作代替多次单文档操作
    • 避免使用正则表达式进行前缀查询

24.3 运维最佳实践

  1. 监控

    • 监控服务器资源使用情况
    • 监控查询性能
    • 监控复制集状态
    • 设置告警阈值
  2. 备份

    • 定期备份数据
    • 测试恢复流程
    • 保存备份记录
    • 考虑使用云服务提供商的备份功能
  3. 安全

    • 启用认证
    • 限制网络访问
    • 定期更新密码
    • 使用TLS/SSL加密传输
  4. 扩展

    • 垂直扩展:增加服务器资源
    • 水平扩展:使用分片集群
    • 根据数据增长和访问模式规划扩展策略

24.4 应用开发最佳实践

  1. 连接管理

    • 使用连接池
    • 正确关闭连接
    • 处理连接异常
  2. 错误处理

    • 捕获并处理MongoDB异常
    • 实现重试机制
    • 记录错误日志
  3. 事务使用

    • 只在必要时使用事务
    • 保持事务简短
    • 考虑使用补偿事务代替长时间运行的事务
  4. 代码组织

    • 使用数据访问层封装MongoDB操作
    • 使用ORM框架简化开发
    • 遵循领域驱动设计原则
相关推荐
longlong int1 小时前
【每日算法】Day 16-1:跳表(Skip List)——Redis有序集合的核心实现原理(C++手写实现)
数据库·c++·redis·算法·缓存
baobao17676408301 小时前
Mysql 数据库编程技术01
数据库·mysql·oracle
一 乐2 小时前
实验室预约|实验室预约小程序|基于Java+vue微信小程序的实验室预约管理系统设计与实现(源码+数据库+文档)
java·数据库·微信小程序·小程序·毕业设计·论文·实验室预约小程序
极限实验室2 小时前
INFINI Labs 产品更新 | Coco AI 0.3 发布 – 新增支持 Widget 外部站点集成
数据库·搜索引擎
我科绝伦(Huanhuan Zhou)2 小时前
MySQL数据库如何在线修改表结构及字段类型?
数据库·mysql
独行soc2 小时前
2025年渗透测试面试题总结- 某四字大厂面试复盘扩展 一面(题目+回答)
java·数据库·python·安全·面试·职场和发展·汽车
rockmelodies2 小时前
【MongoDB + 向量搜索引擎】MongoDB Atlas 向量搜索 提供全托管解决方案
数据库·mongodb·搜索引擎
王佑辉2 小时前
【mongodb】MongoDB的应用场景
mongodb
西元.3 小时前
详解 Redis repl_backlog_buffer(如何判断增量同步)
数据库·redis·缓存
老华带你飞4 小时前
木里风景文化|基于Java+vue的木里风景文化管理平台的设计与实现(源码+数据库+文档)
java·数据库·vue.js·毕业设计·论文·风景·木里风景文化管理平台