MongoDB

一、什么是 MongoDB

MongoDB 是一个开源的 文档型数据库 ,属于 NoSQL 数据库家族。与传统的关系型数据库 (如 MySQL) 使用表和行来存储数据不同,MongoDB 使用灵活的 文档(类似于 JSON 对象)来存储数据。

1. 主要特点

  • 文档模型: 数据存储为类似 JSON 的 BSON 文档(Binary JSON),结构灵活,一个集合内的文档可以有不同的结构。
  • 灵活的模式: 无需预先定义严格的表结构(Schema),数据结构可以随时间演变。
  • 高性能: 支持索引、聚合管道等,优化查询速度。
  • 高可用性: 通过 副本集 (Replica Set) 提供自动故障转移和数据冗余。
  • 水平可扩展性: 通过 分片 (Sharding) 将数据分布在多个服务器上,处理海量数据和高吞吐量。
  • 丰富的查询语言: 支持复杂的查询、聚合、地理空间查询等。
  • 多种存储引擎: 支持 WiredTiger(默认,提供文档级并发控制、压缩和加密)等。
  • 聚合框架: 强大的数据处理管道,用于复杂的数据转换和分析。
  • 地理空间支持: 内置地理空间索引和查询功能。

2. MongoDB 概念解析

  • 文档 (Document): MongoDB 中的基本数据单元。它是一个键值对的有序集合,类似于 JSON 对象。例如:

    json 复制代码
    {
      "_id": ObjectId("5099803df3f4948bd2f98391"),
      "name": "张三",
      "age": 30,
      "hobbies": ["阅读", "游泳"],
      "address": {
        "city": "北京",
        "street": "中关村大街"
      }
    }
  • 集合 (Collection): 一组 MongoDB 文档的容器。类似于关系型数据库中的"表"。

  • 数据库 (Database): 多个集合的逻辑分组。一个 MongoDB 服务器可以承载多个数据库。

  • _id 字段: 每个文档都必须有一个唯一的 _id 字段作为主键。如果插入时未提供,MongoDB 会自动生成一个 ObjectId

  • 嵌入式文档 (Embedded Document): 文档中可以嵌套其他文档(如上例中的 address)。

  • 引用式文档 (Document Reference): 一个文档可以通过存储另一个文档的 _id 来引用它(类似于关系型数据库的外键),实现数据关联。

3. 完整术语列表

  • 文档 (Document)
  • 集合 (Collection)
  • 数据库 (Database)
  • _id (Primary Key)
  • 字段 (Field) / 键 (Key)
  • 值 (Value)
  • BSON (Binary JSON)
  • 副本集 (Replica Set)
  • 主节点 (Primary)
  • 从节点 (Secondary)
  • 仲裁节点 (Arbiter)
  • 分片 (Sharding)
  • 分片键 (Shard Key)
  • 配置服务器 (Config Server)
  • 查询路由器 (mongos)
  • 索引 (Index)
  • 聚合管道 (Aggregation Pipeline)
  • CRUD 操作 (Create, Read, Update, Delete)
  • MongoDB Shell (mongosh)
  • mongod (数据库服务进程)
  • mongos (分片集群查询路由进程)
  • WiredTiger (存储引擎)

二、MongoDB 安装 (dnf)

以下是在基于 RHEL/CentOS/Fedora 的系统上使用 dnf 安装 MongoDB Community Edition 的基本步骤 (以 MongoDB 7.0 为例,版本号会随时间变化,请参考官方文档获取最新指导):

配置仓库:

bash 复制代码
sudo tee /etc/yum.repos.d/mongodb-org-7.0.repo <<EOL
[mongodb-org-7.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/\$releasever/mongodb-org/7.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/packages/server-7.0.asc
EOL

请确保 $releasever 变量正确指向您的系统版本号 (如 8, 9)。
2.

安装 MongoDB 包:

bash 复制代码
sudo dnf install -y mongodb-org

这将安装 mongodb-org-server (mongod), mongodb-org-mongos, mongodb-org-shell (mongosh), mongodb-org-tools (包含 mongodump, mongorestore 等) 和 mongodb-org-database-tools-extra
3.

启动 MongoDB 服务并设置开机自启:

bash 复制代码
sudo systemctl start mongod
sudo systemctl enable mongod

验证服务状态:

bash 复制代码
sudo systemctl status mongod

应该看到 active (running) 状态。
5.

(可选) 连接验证: 使用 mongosh 连接本地实例:

bash 复制代码
mongosh

如果成功,会看到 MongoDB Shell 的提示符。

三、 MongoDB Shell

MongoDB Shell (mongosh) 是一个功能强大的交互式 JavaScript 接口,用于管理 MongoDB 实例、执行查询、更新数据等。

1. 安装 MongoDB Shell

在基于 dnf 的系统上,安装 MongoDB 时通常已经包含了 mongodb-org-shell 包。如果只需要 Shell:

bash 复制代码
sudo dnf install -y mongodb-org-shell

2. 验证 MongoDB Shell

  • 检查版本:

    bash 复制代码
    mongosh --version
  • 连接本地 MongoDB 实例:

    bash 复制代码
    mongosh

    默认连接 mongodb://localhost:27017。成功连接后,会显示 Shell 版本、连接 URI、服务器版本等信息。

  • 运行简单命令:mongosh 提示符下,输入:

    javascript 复制代码
    db.version()

    应该返回 MongoDB 服务器的版本号。

四、 数据库管理

mongosh 中操作数据库。

1. 查看数据库列表

javascript 复制代码
show dbs

列出当前 MongoDB 实例中所有非空的数据库(系统数据库除外)。新创建的、没有集合的数据库不会显示。

2. 创建数据库

MongoDB 在您首次向一个数据库中的集合插入数据时隐式创建该数据库。使用 use 命令切换上下文:

javascript 复制代码
use myNewDatabase

这会切换到 myNewDatabase。如果该数据库不存在,此时它尚未被真正创建。只有当您在其中创建一个集合并插入文档后:

javascript 复制代码
db.myCollection.insertOne({ name: "Test" })

myNewDatabase 才会出现在 show dbs 的结果中。

3. 删除数据库

先切换到要删除的数据库,然后执行:

javascript 复制代码
use databaseToDelete
db.dropDatabase()

这会删除当前选中的数据库及其所有集合。

4. 默认数据库

  • test: 如果您在 mongosh 中未使用 use 命令指定数据库就执行插入操作,数据会进入 test 数据库。
  • admin: 存储用户认证和权限信息的系统数据库。
  • local: 存储副本集特定信息的数据库。此数据库的内容不会复制到副本集的其他节点。
  • config: 在分片集群中存储分片和块元数据的数据库。

5. 系统内置数据库

  • admin
  • local
  • config (分片集群中) 这些数据库对 MongoDB 的内部运作至关重要,通常不应直接修改它们。

五、 集合管理

mongosh 中,使用 db 对象代表当前数据库。

1. 查看集合

javascript 复制代码
show collections
// 或
db.getCollectionNames()

列出当前数据库中的所有集合。

2. 创建集合

  • 显式创建: 可以指定选项(如大小限制、文档校验规则):

    javascript 复制代码
    db.createCollection("myNewCollection", {
      capped: true, // 固定集合
      size: 100000, // 大小(字节)
      max: 1000     // 最大文档数
    })
  • 隐式创建: 当您向一个不存在的集合插入文档时,集合会被自动创建:

    javascript 复制代码
    db.myImplicitCollection.insertOne({ x: 1 })

3. 更新集合名

javascript 复制代码
db.oldCollectionName.renameCollection("newCollectionName")

将集合 oldCollectionName 重命名为 newCollectionName

4. 删除集合

javascript 复制代码
db.collectionToDrop.drop()

删除当前数据库中的 collectionToDrop 集合及其所有文档。

六、 文档操作

1. 插入文档

  • 插入单个文档:

    javascript 复制代码
    db.collection.insertOne({
      name: "Alice",
      age: 25,
      email: "alice@example.com"
    })
  • 插入多个文档:

    javascript 复制代码
    db.collection.insertMany([
      { name: "Bob", age: 30 },
      { name: "Charlie", age: 35 }
    ])

2. 查询文档

  • 查询所有文档:

    javascript 复制代码
    db.collection.find()
  • 条件查询:

    javascript 复制代码
    db.collection.find({ age: { $gt: 30 } }) // 年龄大于30
    db.collection.find({ name: "Alice" }) // 名字是Alice
  • 投影(选择返回字段):

    javascript 复制代码
    db.collection.find({}, { name: 1, email: 1 }) // 只返回 name 和 email 字段,_id 默认返回
    db.collection.find({}, { name: 1, _id: 0 }) // 只返回 name 字段,排除 _id
  • 排序:

    javascript 复制代码
    db.collection.find().sort({ age: 1 }) // 年龄升序 (1)
    db.collection.find().sort({ age: -1 }) // 年龄降序 (-1)
  • 限制结果数量:

    javascript 复制代码
    db.collection.find().limit(5)
  • 跳过文档:

    javascript 复制代码
    db.collection.find().skip(10)

3. 删除文档

  • 删除匹配条件的文档:

    javascript 复制代码
    db.collection.deleteMany({ age: { $lt: 20 } }) // 删除所有年龄小于20的文档
  • 删除最多一个匹配条件的文档:

    javascript 复制代码
    db.collection.deleteOne({ name: "ToDelete" })
  • 删除所有文档(保留集合):

    javascript 复制代码
    db.collection.deleteMany({})

4. 更新文档

  • 更新匹配条件的单个文档:

    javascript 复制代码
    db.collection.updateOne(
      { name: "Alice" }, // 查询条件
      { $set: { age: 26 } } // 更新操作:将 age 设置为 26
    )
  • 更新匹配条件的所有文档:

    javascript 复制代码
    db.collection.updateMany(
      { department: "Sales" }, // 查询条件
      { $set: { bonus: 1000 } } // 更新操作:给所有销售部门员工设置 bonus 为 1000
    )
  • 替换文档:

    javascript 复制代码
    db.collection.replaceOne(
      { name: "Alice" }, // 查询条件
      { name: "Alice Smith", age: 26, job: "Engineer" } // 新文档(完全替换)
    )

    常用更新操作符:$set, $unset, $inc, $push, $pull, $rename 等。

七、 MongoDB 备份与恢复

使用 mongodumpmongorestore 工具进行逻辑备份和恢复。

1. 安装备份与恢复命令

在基于 dnf 的系统上,安装 MongoDB 时通常已经包含了 mongodb-org-tools 包 (包含 mongodump, mongorestore)。如果只需要工具:

bash 复制代码
sudo dnf install -y mongodb-org-tools

2. MongoDB 数据备份

  • 备份整个实例 (所有数据库):

    bash 复制代码
    mongodump --uri="mongodb://localhost:27017" --out=/path/to/backup/directory
  • 备份指定数据库:

    bash 复制代码
    mongodump --uri="mongodb://localhost:27017" --db=myDatabase --out=/path/to/backup/directory
  • 备份指定集合:

    bash 复制代码
    mongodump --uri="mongodb://localhost:27017" --db=myDatabase --collection=myCollection --out=/path/to/backup/directory
  • 带认证备份: 在 URI 中包含用户名和密码,或使用 --username--password 选项。

3. MongoDB 数据恢复

  • 恢复整个备份目录 (到原数据库名):

    bash 复制代码
    mongorestore --uri="mongodb://localhost:27017" /path/to/backup/directory
  • 恢复指定数据库:

    bash 复制代码
    mongorestore --uri="mongodb://localhost:27017" --db=myDatabase /path/to/backup/directory/myDatabase
  • 恢复指定集合:

    bash 复制代码
    mongorestore --uri="mongodb://localhost:27017" --db=myDatabase --collection=myCollection /path/to/backup/directory/myDatabase/myCollection.bson
  • 带认证恢复: 同样在 URI 中包含用户名和密码,或使用 --username--password 选项。

  • --drop 选项: 在恢复数据之前删除目标数据库或集合中的现有数据。慎用!

八、 MongoDB 用户管理

MongoDB 使用基于角色的访问控制 (Role-Based Access Control, RBAC) 来管理用户权限。用户创建在特定的数据库中,但角色可以授予跨数据库的权限。

基本操作:

  1. 启用访问控制: 通常需要在配置文件 (/etc/mongod.conf) 中设置 security.authorization: enabled 并重启 mongod,或在启动时添加 --auth 参数。重要提示:在启用认证前,必须先创建至少一个具有 userAdminuserAdminAnyDatabase 角色的管理员用户!

  2. 以管理员身份连接: 使用具有管理权限的账户连接 mongosh

    bash 复制代码
    mongosh "mongodb://adminUser:adminPassword@localhost:27017/admin?authSource=admin"
  3. 创建用户:

    javascript 复制代码
    use admin // 通常在 admin 数据库创建管理用户
    db.createUser({
      user: "myAdmin",
      pwd: "myStrongPassword", // 或使用 passwordPrompt() 交互式输入
      roles: [ { role: "userAdminAnyDatabase", db: "admin" }, "readWriteAnyDatabase" ]
    })
    • user: 用户名。
    • pwd: 密码。强烈建议使用 passwordPrompt() 避免在命令历史中留下明文密码。
    • roles: 分配给用户的角色数组。角色指定权限 (read, readWrite, dbAdmin, userAdmin 等)。角色可以限定在特定数据库 ({ role: "readWrite", db: "myAppDB" }) 或使用 AnyDatabase 版本 (readWriteAnyDatabase)。
  4. 查看用户:

    javascript 复制代码
    db.getUsers() // 查看当前数据库的用户
    use admin
    db.getUsers() // 查看 admin 数据库的用户
  5. 更新用户:

    javascript 复制代码
    db.updateUser("myAdmin", {
      pwd: passwordPrompt(), // 更新密码
      roles: [ { role: "userAdminAnyDatabase", db: "admin" }, "readWriteAnyDatabase", { role: "dbAdmin", db: "reportingDB" } ] // 更新角色
    })
  6. 删除用户:

    javascript 复制代码
    db.dropUser("userToDelete")

最佳实践:

  • admin 数据库创建管理员用户。
  • 为应用程序创建专用用户,仅授予其访问特定数据库所需的最小权限(如 readWrite)。
  • 使用强密码。
  • 避免使用 root 角色(除非绝对必要)。
  • 使用 passwordPrompt() 或在脚本中读取环境变量来避免密码泄露。
  • 定期审查用户和权限。
相关推荐
m0_743623922 小时前
React 自定义 Hook 的命名规范与调用规则详解
jvm·数据库·python
古城小栈2 小时前
GORM 操作 PostgreSQL 高级类型
数据库·postgresql
ward RINL2 小时前
redis分页查询
数据库·redis·缓存
Treh UNFO2 小时前
Redis-配置文件
数据库·redis·oracle
iNgs IMAC2 小时前
Redis之Redis事务
java·数据库·redis
oLLI PILO2 小时前
Redis连接池
数据库·redis·缓存
看海的四叔3 小时前
【SQL】SQL同环比计算的多种实现方式
数据库·hive·sql·mysql·数据分析·同环比
qq_333120973 小时前
Sql Server数据库远程连接访问配置
数据库
yaodong5183 小时前
PostgreSQL_安装部署
数据库·postgresql