一、什么是 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
-
检查版本:
bashmongosh --version -
连接本地 MongoDB 实例:
bashmongosh默认连接
mongodb://localhost:27017。成功连接后,会显示 Shell 版本、连接 URI、服务器版本等信息。 -
运行简单命令: 在
mongosh提示符下,输入:javascriptdb.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. 系统内置数据库
adminlocalconfig(分片集群中) 这些数据库对 MongoDB 的内部运作至关重要,通常不应直接修改它们。
五、 集合管理
在 mongosh 中,使用 db 对象代表当前数据库。
1. 查看集合
javascript
show collections
// 或
db.getCollectionNames()
列出当前数据库中的所有集合。
2. 创建集合
-
显式创建: 可以指定选项(如大小限制、文档校验规则):
javascriptdb.createCollection("myNewCollection", { capped: true, // 固定集合 size: 100000, // 大小(字节) max: 1000 // 最大文档数 }) -
隐式创建: 当您向一个不存在的集合插入文档时,集合会被自动创建:
javascriptdb.myImplicitCollection.insertOne({ x: 1 })
3. 更新集合名
javascript
db.oldCollectionName.renameCollection("newCollectionName")
将集合 oldCollectionName 重命名为 newCollectionName。
4. 删除集合
javascript
db.collectionToDrop.drop()
删除当前数据库中的 collectionToDrop 集合及其所有文档。
六、 文档操作
1. 插入文档
-
插入单个文档:
javascriptdb.collection.insertOne({ name: "Alice", age: 25, email: "alice@example.com" }) -
插入多个文档:
javascriptdb.collection.insertMany([ { name: "Bob", age: 30 }, { name: "Charlie", age: 35 } ])
2. 查询文档
-
查询所有文档:
javascriptdb.collection.find() -
条件查询:
javascriptdb.collection.find({ age: { $gt: 30 } }) // 年龄大于30 db.collection.find({ name: "Alice" }) // 名字是Alice -
投影(选择返回字段):
javascriptdb.collection.find({}, { name: 1, email: 1 }) // 只返回 name 和 email 字段,_id 默认返回 db.collection.find({}, { name: 1, _id: 0 }) // 只返回 name 字段,排除 _id -
排序:
javascriptdb.collection.find().sort({ age: 1 }) // 年龄升序 (1) db.collection.find().sort({ age: -1 }) // 年龄降序 (-1) -
限制结果数量:
javascriptdb.collection.find().limit(5) -
跳过文档:
javascriptdb.collection.find().skip(10)
3. 删除文档
-
删除匹配条件的文档:
javascriptdb.collection.deleteMany({ age: { $lt: 20 } }) // 删除所有年龄小于20的文档 -
删除最多一个匹配条件的文档:
javascriptdb.collection.deleteOne({ name: "ToDelete" }) -
删除所有文档(保留集合):
javascriptdb.collection.deleteMany({})
4. 更新文档
-
更新匹配条件的单个文档:
javascriptdb.collection.updateOne( { name: "Alice" }, // 查询条件 { $set: { age: 26 } } // 更新操作:将 age 设置为 26 ) -
更新匹配条件的所有文档:
javascriptdb.collection.updateMany( { department: "Sales" }, // 查询条件 { $set: { bonus: 1000 } } // 更新操作:给所有销售部门员工设置 bonus 为 1000 ) -
替换文档:
javascriptdb.collection.replaceOne( { name: "Alice" }, // 查询条件 { name: "Alice Smith", age: 26, job: "Engineer" } // 新文档(完全替换) )常用更新操作符:
$set,$unset,$inc,$push,$pull,$rename等。
七、 MongoDB 备份与恢复
使用 mongodump 和 mongorestore 工具进行逻辑备份和恢复。
1. 安装备份与恢复命令
在基于 dnf 的系统上,安装 MongoDB 时通常已经包含了 mongodb-org-tools 包 (包含 mongodump, mongorestore)。如果只需要工具:
bash
sudo dnf install -y mongodb-org-tools
2. MongoDB 数据备份
-
备份整个实例 (所有数据库):
bashmongodump --uri="mongodb://localhost:27017" --out=/path/to/backup/directory -
备份指定数据库:
bashmongodump --uri="mongodb://localhost:27017" --db=myDatabase --out=/path/to/backup/directory -
备份指定集合:
bashmongodump --uri="mongodb://localhost:27017" --db=myDatabase --collection=myCollection --out=/path/to/backup/directory -
带认证备份: 在 URI 中包含用户名和密码,或使用
--username和--password选项。
3. MongoDB 数据恢复
-
恢复整个备份目录 (到原数据库名):
bashmongorestore --uri="mongodb://localhost:27017" /path/to/backup/directory -
恢复指定数据库:
bashmongorestore --uri="mongodb://localhost:27017" --db=myDatabase /path/to/backup/directory/myDatabase -
恢复指定集合:
bashmongorestore --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) 来管理用户权限。用户创建在特定的数据库中,但角色可以授予跨数据库的权限。
基本操作:
-
启用访问控制: 通常需要在配置文件 (
/etc/mongod.conf) 中设置security.authorization: enabled并重启mongod,或在启动时添加--auth参数。重要提示:在启用认证前,必须先创建至少一个具有userAdmin或userAdminAnyDatabase角色的管理员用户! -
以管理员身份连接: 使用具有管理权限的账户连接
mongosh:bashmongosh "mongodb://adminUser:adminPassword@localhost:27017/admin?authSource=admin" -
创建用户:
javascriptuse 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)。
-
查看用户:
javascriptdb.getUsers() // 查看当前数据库的用户 use admin db.getUsers() // 查看 admin 数据库的用户 -
更新用户:
javascriptdb.updateUser("myAdmin", { pwd: passwordPrompt(), // 更新密码 roles: [ { role: "userAdminAnyDatabase", db: "admin" }, "readWriteAnyDatabase", { role: "dbAdmin", db: "reportingDB" } ] // 更新角色 }) -
删除用户:
javascriptdb.dropUser("userToDelete")
最佳实践:
- 在
admin数据库创建管理员用户。 - 为应用程序创建专用用户,仅授予其访问特定数据库所需的最小权限(如
readWrite)。 - 使用强密码。
- 避免使用
root角色(除非绝对必要)。 - 使用
passwordPrompt()或在脚本中读取环境变量来避免密码泄露。 - 定期审查用户和权限。