📖 第一章:MongoDB简介、安装 、概念解析、用户管理、连接、实际应用示例
文章目录
1.1 MongoDB简介
MongoDB 是一个文档型数据库,数据以 BSON 格式存储,结构类似 JSON 对象。
核心概念:
- 数据库(Database):数据存储容器
- 集合(Collection):数据库中的数据集合,相当于关系型数据库的表
- 文档(Document):集合中的单条记录,由键值对组成,相当于关系型数据库的行
核心概念对比:
关系型数据库 → MongoDB
数据库(Database) → 数据库(Database)
表(Table) → 集合(Collection)
行(Row) → 文档(Document)
列(Column) → 字段(Field)
数据存储特性:文档结构灵活,字段值可包含其他文档、数组或文档数组。支持嵌套结构,无需预定义模式。(MongoDB就像一个超级灵活的电子档案柜。传统的关系型数据库(如MySQL)就像严格的表格,每一行都必须有相同的列。而MongoDB更像是一个可以存放各种形状文件夹的柜子,每个文件夹里的内容可以完全不同。)
查询与索引:
- 支持为任意字段创建索引,提升查询和排序性能
- 使用 JSON 格式查询语法,支持复杂查询表达式
- 支持对嵌套对象和数组的查询操作
扩展性:
- 数据副本:通过本地或网络创建数据镜像,实现冗余备份
- 水平扩展:使用分片技术将数据分布到多个节点,应对负载增长
数据操作:
- 使用 update() 命令进行文档替换或字段更新
- MapReduce 功能处理大规模数据聚合,使用 JavaScript 编写 Map 和 Reduce 函数
- GridFS 存储超过 BSON 限制的大文件(如图片、视频)
开发支持:
- 服务端可执行 JavaScript 脚本
- 支持多种编程语言:Ruby、Python、Java、C++、PHP、C#
- 安装部署简单
MongoDB优势总结:
- 灵活的数据结构:不需要预定义表结构
- JSON格式存储:天然支持复杂的嵌套数据
- 水平扩展:容易分布式部署
- 强大的查询能力:支持复杂的聚合操作
1.2 Mongo安装
1.2.1 MongoDB-Windows安装
从 MongoDB 官网下载安装,MongoDB 预编译二进制包下载地址:https://www.mongodb.com/try/download/community
下载 .msi 文件,下载后双击该文件,按操作提示安装即可。
安装过程:
点击Next,默认勾选MongoDB Compass,MongoDB Compass是MongoDB官方推出的图形化用户界面(GUI)工具,专为简化MongoDB数据库的管理、查询和分析而设计。它提供了直观的可视化界面,用户无需编写复杂的命令行代码,就能轻松完成数据库连接、集合(Collection)浏览、文档(Document)增删改查、索引管理、数据导入导出等操作。同时,它还具备实时性能监控、查询性能分析等功能,帮助开发者和数据库管理员更高效地调试和优化MongoDB数据库,尤其适合初学者快速上手MongoDB,或用于日常开发中的数据管理工作。我这里直接默认安装。
至此,安装完成,安装成功后可以在任务管理器服务里看的MongoDB服务:
或者直接在浏览器中输入:
1.2.2 MongoDB-Linux安装
参考菜鸟教程:Linux MongoDB
1.2.3 MongoDB-Mac安装
参考菜鸟教程:OSX MongoDB
1.3 MongoDB Shell安装
MongoDB Shell(简称 mongosh)是 MongoDB 官方提供的交互式命令行工具,用于通过命令与 MongoDB 数据库直接交互,支持运行查询、管理数据、执行脚本等操作。它替代了旧版的 mongo 工具,提供更完善的语法高亮、自动补全、错误提示等功能,同时支持 JavaScript 语法和 MongoDB 扩展命令,是开发者在终端环境下操作 MongoDB 的核心工具,常用于数据库调试、数据查询、脚本执行等场景。
安装比较简单,可以参考菜鸟教程的 MongoDB Shell安装,只不过也是分Windows、Linux和Mac系统,我这里是Windows下安装,具体过程如下:
访问官方地址:https://www.mongodb.com/try/download/shell,选择适合 Windows 的 MongoDB Shell 版本,我这选的msi格式(zip的其实解压出来就是msi双击安装完的样子,只不过mongosh.exe是放在了bin文件夹中,因此,选择下载哪种格式都一样),下载后双击安装程序,可以更换安装目录。
来到 MongoDB Shell安装目录中,双击其中的mongosh.exe
,会显示Please enter a MongoDB connection string (Default: mongodb://localhost/):
的字样。
意在让你输入连接 MongoDB 数据库的连接字符串(如默认的 mongodb://localhost/
就是连接本地 MongoDB 的字符串,保持默认可以直接回车),这里输入的字符串会被优先解析为完整的连接字符串(用于指定服务器地址、端口等连接信息),而非单纯的服务器名或数据库名。连接字符串的格式通常是 mongodb://<host>:<port>/<database>
,其中:
<host>:<port>
用于指定服务器地址和端口(如 localhost:27017);- 末尾的 可选,用于指定连接后默认进入的数据库(若不指定,默认进入 test 数据库)。
如果输入的是非标准连接字符串的普通字符串(如随便输入 abc),mongosh 会尝试按以下规则解析:
- 先假设这是一个简化的连接字符串,默认补充服务器地址为
localhost:27017
,形成mongodb://localhost:27017/abc
; - 此时,
localhost:27017
是服务器地址,abc
被当作连接后默认进入的数据库名(若不存在则临时创建)。
简言之:输入的字符串主要用于补充连接信息中的 “默认数据库名”,而服务器地址会默认使用 localhost:27017
(除非字符串中明确包含服务器地址,如mongodb://192.168.1.1:27017/mydb
)。
这是手动双击启动mongosh.exe
的连接。
实际中,安装好了MongoDB Shell了,可以直接命令中输入mongosh
,如果 MongoDB 服务器运行在本地默认端口(27017),则可以直接连接。简单说,mongosh 就像一个 “开关”—— 在命令行中输入它,会直接启动 MongoDB 官方的交互式命令行工具,让你进入可以操作 MongoDB 数据库的环境。这里说的进入环境指的是:关联一个默认数据库,即输入了mongosh
连接成功后,会自动进入名为 test 的默认数据库(如果该数据库不存在,会在首次操作时自动创建)。
如果你的 MongoDB 服务器是默认配置(运行在本地、端口 27017),输入 mongosh
后会自动连接到本地默认数据库test,直接进入操作界面(可以输入查询、创建集合等命令);如果需要连接其他服务器或非默认端口,就用 mongosh --host <地址>:<端口>
这种形式,本质还是通过 mongosh 指令启动工具,再附加连接参数。
- 其中
<hostname>
是 MongoDB 服务器的主机名或 IP 地址 <port>
是 MongoDB 服务器的端口号
查看版本的话,命令行可以直接输入mongosh --version
来查看。
进入数据库后,可以执行各种 MongoDB 数据库操作(这些操作后面会详细讲述):
- 查看当前数据库:
db
- 显示数据库列表:
show dbs
- 切换到指定数据库:
use <database_name>
- 执行查询操作:
db.<collection_name>.find()
- 插入文档:
db.<collection_name>.insertOne({ ... })
- 更新文档:
db.<collection_name>.updateOne({ ... })
- 删除文档:
db.<collection_name>.deleteOne({ ... })
- 退出 MongoDB Shell:
quit()
或者exit
1.4 MongoDB概念解析
1.4.1 基础概念
MongoDB是一个文档型数据库,和传统的关系型数据库(如MySQL)有很大不同。关系型数据库就像整齐的表格,而MongoDB更像灵活的文件夹。
核心概念对比:
关系型数据库 | MongoDB | 简单理解 |
---|---|---|
数据库(database) | 数据库(database) | 存放数据的容器 |
表(table) | 数据库表/集合(Collection) | 存放同类数据的容器 |
行(row) | 数据记录行/文档(Document) | 一条具体的数据记录 |
列(column) | 数据字段/域(Field) | 数据的属性 |
索引(index) | 索引(index) | 索引 |
主键(primary key) | _id字段 | 每条数据的唯一标识 |
在MongoDB中基本的概念是:文档、集合、数据库,下面我们挨个介绍。
文档(Document):MongoDB 的基本数据单元,通常是一个 JSON-like 的结构,可以包含多种数据类型。
集合(Collection):类似于关系型数据库中的表,集合是一组文档的容器。在 MongoDB 中,一个集合中的文档不需要有一个固定的模式。
数据库(Database):包含一个或多个集合的 MongoDB 实例。
其它比较重要的概念:
- BSON:Binary JSON 的缩写,是 MongoDB 用来存储和传输文档的二进制形式的 JSON。
- 索引(Index):用于优化查询性能的数据结构,可以基于集合中的一个或多个字段创建索引。
- GridFS:用于存储和检索大于 BSON 文档大小限制的文件的规范。
- ObjectId:MongoDB 为每个文档自动生成的唯一标识符。
- CRUD 操作:创建(Create)、读取(Read)、更新(Update)、删除(Delete)操作。
- 操作符(Operators):用于查询和更新文档的特殊字段。
- 连接(Join):MongoDB 允许在查询中使用
$lookup
操作符来实现类似 SQL 的连接操作。 - TTL(Time-To-Live):可以为集合中的某些字段设置 TTL,以自动删除旧数据。
1.4.2 数据库
一个 MongoDB 中可以建立多个数据库。
如果在操作时没有指定数据库,MongoDB 会使用一个名为 test 的默认数据库,该数据库存储在data
目录中。
MongoDB 的单个实例可以容纳多个独立的数据库,每一个都有自己的集合和权限,不同的数据库也放置在不同的文件中。
这里说的 “单个实例” 指的是一个正在运行的 MongoDB 服务器进程(mongod 进程)。
简单说,当你通过 mongod
命令启动 MongoDB 服务后,会在操作系统中生成一个独立的进程,这个进程就是 “单个实例”。它可以管理多个相互独立的数据库(比如一个存储用户数据的 user_db
、一个存储日志的 log_db
等),每个数据库有自己的集合、文档和权限设置,且物理上存储在不同的文件中(默认位于 MongoDB 数据目录的子文件夹中,每个数据库对应一个子文件夹)。
这个设计的好处是:通过一个服务器进程即可管理多个数据库,无需为每个数据库单独启动进程,既节省系统资源,又便于集中管理。
PS:关于mongod
命令放在本章最后进行讲解。
MongoDB可以同时运行多个数据库,每个数据库都是独立的。
// 查看所有数据库
> show dbs
admin 0.000GB
local 0.000GB
test 0.000GB
// 查看当前使用的数据库
> db
test
// 切换到指定数据库
> use mydatabase
switched to db mydatabase
数据库命名规则:
- 不能为空字符串
- 不能包含空格、点号、美元符号、斜杠、反斜杠
- 全部小写
- 最多64个字符
特殊数据库:
admin
:管理员数据库,拥有所有权限local
:本地数据库,不会被复制config
:分片配置数据库
特殊数据库的详细介绍:
- admin 数据库:这是MongoDB的"超级管理员"数据库,相当于系统的root用户。在这里创建的用户自动获得所有数据库的管理权限,可以执行关键的服务器管理命令如关闭服务器、列出所有数据库等。它包含重要的系统集合,在生产环境中只允许数据库管理员访问。
- local 数据库:这是一个特殊的本地数据库,其数据永远不会被复制到其他服务器。它适合存储本地服务器特有的数据,如本地日志、临时数据、服务器配置等。在副本集环境中特别有用,因为每个节点可以存储自己特有的信息,不会影响副本集同步性能。
- config 数据库这是分片集群架构的核心组件,专门存储分片集群的元数据和配置信息。它包含多个重要集合,记录分片服务器信息、数据库配置、分片键信息、数据块分布等。整个分片集群的所有组件都需要访问它来获取配置信息,因此其高可用性对整个集群至关重要。
1.4.3 文档(Document) - 数据的核心
文档是MongoDB的基本数据单元,本质上是JSON格式的数据。每个文档可以有不同的结构,这是MongoDB最大的特点。
例如下图中的两个文档:
下表列出了 RDBMS 与 MongoDB 对应的术语:
RDBMS | MongoDB |
---|---|
数据库 | 数据库 |
表格 | 集合 |
行 | 文档 |
列 | 字段 |
表联合 | 嵌入文档 |
主键 | 主键 (MongoDB 提供了 key 为 _id ) |
// 简单的文档
{"name": "张三", "age": 25}
// 复杂的文档
{
"name": "李四",
"age": 30,
"email": "lisi@example.com",
"address": {
"city": "北京",
"street": "中关村大街"
},
"hobbies": ["读书", "游泳", "编程"],
"created_at": new Date()
}
文档的特点:
- 字段名(键)是字符串
- 字段值可以是任何类型(字符串、数字、布尔值、数组、对象等、甚至可以是整个嵌入的文档)
- 文档中的键/值对是有序的。
- 不能有重复的字段名(键)
- 区分大小写
文档键命名规范:
- 键不能含有
\0
(空字符)。这个字符用来表示键的结尾。 .
和$
有特别的意义,只有在特定环境下才能使用。- 以下划线
_
开头的键是保留的(不是严格要求的)。
1.4.4 集合(Collection) - 文档的容器
集合就像文件夹(文档组),存放相关的文档。一个数据库可以有多个集合。
集合(Collection)是文档(Document)的容器,类似于关系型数据库中的 “表”,但它的核心特点是无固定结构—— 这意味着你可以往同一个集合里插入格式、字段完全不同的文档,不需要提前定义 “表结构”。不过实际使用中,集合里的文档通常会有逻辑关联(比如都属于 “用户” 或 “订单” 相关数据),这样更便于管理和查询。
例如,可以创建一个名为products
的集合,用来存储各类商品信息,其中的文档可以有完全不同的字段:
// 插入第一个文档(包含名称、价格、类别字段)
db.products.insertOne({ name: "笔记本电脑", price: 5999, category: "电子设备" })
// 插入第二个文档(比第一个多了“品牌”和“库存”字段,少了“类别”字段)
db.products.insertOne({ name: "机械键盘", price: 399, brand: "Keychron", stock: 120 })
// 插入第三个文档(字段与前两个完全不同,包含“重量”和“材质”)
db.products.insertOne({ name: "帆布包", weight: 0.3, material: "棉麻" })
当执行第一条insertOne命令时,products集合会被自动创建,后续即使插入结构差异很大的文档,集合也能正常存储。这种灵活性让 MongoDB 非常适合处理数据格式多变的场景(比如电商平台中不同类型商品的属性差异),无需像关系型数据库那样为每种商品单独建表。
// 创建集合(插入第一个文档时自动创建)
> db.users.insertOne({"name": "王五", "age": 28})
// 查看所有集合
> show collections
users
products
// 查看集合中的文档数量
> db.users.countDocuments()
1
集合命名规则:
- 不能为空字符串
- 不能包含空字符(
\0
) - 不能以"system."开头(系统保留)
- 避免使用
$
符号
固定集合(Capped Collection):固定集合是大小固定的集合,类似于循环缓冲区。
// 创建固定集合,大小100000字节
> db.createCollection("logs", {capped: true, size: 100000})
// 固定集合的特点:
// 1. 大小固定,超出时会删除最旧的文档
// 2. 不能删除单个文档,只能删除整个集合
// 3. 适合存储日志等时间序列数据
系统集合:MongoDB在每个数据库中都有系统集合,用于存储元数据:
// 查看系统集合
> db.system.namespaces.find() // 所有集合信息
> db.system.indexes.find() // 所有索引信息
> db.system.users.find() // 用户信息
> db.system.profile.find() // 性能分析信息
1.4.5 数据类型详解
MongoDB支持丰富的数据类型:
数据类型 | 描述 |
---|---|
String | 字符串。存储数据常用的数据类型。在 MongoDB 中,UTF-8 编码的字符串才是合法的。 |
Integer | 整型数值。用于存储数值。根据你所采用的服务器,可分为 32 位或 64 位。 |
Boolean | 布尔值。用于存储布尔值(真/假)。 |
Double | 双精度浮点值。用于存储浮点值。 |
Min/Max keys | 将一个值与 BSON(二进制的 JSON)元素的最低值和最高值相对比。 |
Array | 用于将数组或列表或多个值存储为一个键。 |
Timestamp | 时间戳。记录文档修改或添加的具体时间。 |
Object | 用于内嵌文档。 |
Null | 用于创建空值。 |
Symbol | 符号。该数据类型基本上等同于字符串类型,但不同的是,它一般用于采用特殊符号类型的语言。 |
Date | 日期时间。用 UNIX 时间格式来存储当前日期或时间。你可以指定自己的日期时间:创建 Date 对象,传入年月日信息。 |
Object ID | 对象 ID。用于创建文档的 ID。 |
Binary Data | 二进制数据。用于存储二进制数据。 |
Code | 代码类型。用于在文档中存储 JavaScript 代码。 |
Regular expression | 正则表达式类型。用于存储正则表达式。 |
例如:
// 字符串
{"name": "张三"}
// 数字
{"age": 25, "price": 99.99}
// 布尔值
{"isActive": true}
// 日期
{"created_at": new Date()}
// 数组
{"tags": ["技术", "编程", "数据库"]}
// 对象
{"address": {"city": "北京", "street": "中关村"}}
// 空值
{"description": null}
下面说明下几种重要的数据类型。
1.4.5.1 ObjectId - 自动生成的主键
每个文档都有一个唯一的_id
字段,类似唯一主键,默认是ObjectId类型。
// ObjectId的组成(12字节)
// 前4字节:时间戳(unix 时间戳,格林尼治时间 UTC 时间,比北京时间晚了 8 个小时)
// 接下来3字节:机器标识
// 接下来2字节:进程ID
// 最后3字节:随机数
MongoDB 中存储的文档必须有一个 _id 键。这个键的值可以是任何类型的,默认是个 ObjectId 对象
由于 ObjectId 中保存了创建的时间戳,所以你不需要为你的文档保存时间戳字段,你可以通过 getTimestamp 函数来获取文档的创建时间,例如:
// 获取ObjectId的创建时间
> var id = ObjectId()
> id.getTimestamp()
ISODate("2024-01-15T10:30:00Z")
// ObjectId转字符串
> id.toString()
"65a4b8c0123456789012345"
1.4.5.2 Date - 日期时间
表示当前距离 Unix新纪元(1970年1月1日)的毫秒数。日期类型是有符号的, 负数表示 1970 年之前的日期。
> var mydate1 = new Date() //格林尼治时间
> mydate1
ISODate("2018-03-04T14:58:51.233Z")
> typeof mydate1
object
> var mydate2 = ISODate() //格林尼治时间
> mydate2
ISODate("2018-03-04T15:00:45.479Z")
> typeof mydate2
object
这样创建的时间是日期类型,需要返回一个时间类型的字符串,可以:
> var mydate1str = mydate1.toString()
> mydate1str
Sun Mar 04 2018 14:58:51 GMT+0000 (UTC)
> typeof mydate1str
string
或者
> Date()
Sun Mar 04 2018 15:02:59 GMT+0000 (UTC)
1.4.5.3 其它特殊类型
// 时间戳(MongoDB内部使用)
{"timestamp": new Timestamp()}
// 二进制数据
{"file": BinData(0, "base64encodeddata")}
// JavaScript代码
{"script": Code("function() { return 'hello'; }")}
// 正则表达式
{"pattern": /^[a-z]+$/}
1.5 用户管理
MongoDB的用户管理就像给房子安装门锁一样,确保只有有权限的人才能访问数据库。如果你的数据库没有用户管理,任何人都可以连接进来查看、修改甚至删除你的数据,这是非常危险的。
用户管理包括:
- 创建用户账号
- 设置密码
- 分配权限(角色)
- 验证身份
- 管理用户
1.5.1 用户和数据库的关系
在MongoDB中,用户是创建在特定数据库中的,但这个用户可以在多个数据库中拥有不同的权限。
例如:
// 在admin数据库中创建用户
use admin
db.createUser({
user: "admin",
pwd: "admin123",
roles: ["userAdminAnyDatabase", "readWriteAnyDatabase"]
})
// 在myapp数据库中创建用户
use myapp
db.createUser({
user: "appuser",
pwd: "app123",
roles: ["readWrite"]
})
其中的roles: ["userAdminAnyDatabase", "readWriteAnyDatabase"]
这两个是 MongoDB 内置的全局角色,用于授予用户跨数据库级的管理和操作权限。
具体说明:
userAdminAnyDatabase
:允许用户管理所有数据库中的用户(创建、修改、删除用户和角色),但不包含数据库数据的读写权限。readWriteAnyDatabase
:允许用户对所有数据库执行读写操作(插入、查询、更新、删除文档等),但不包含用户管理权限。
这两个角色组合后,admin 用户就具备了 “管理所有数据库的用户” 和 “操作所有数据库数据” 的超级权限,适合作为超级管理员” 账号(通常仅在 admin 数据库中创建这类高权限用户)。
对比我这里创建的 appuser
用户:
- 角色
readWrite
未指定数据库(默认作用于当前数据库 myapp),因此该用户仅能读写myapp
数据库,权限范围局限于单个数据库,更适合业务应用使用。
高权限用户通常创建在 admin 数据库并使用全局角色,普通用户创建在业务数据库并使用局部角色。
1.5.2 角色(Roles)的概念
角色决定了用户能做什么:
- read:只能读取数据
- readWrite:可以读取和写入数据
- dbAdmin:可以管理数据库(创建集合、索引等)
- userAdmin:可以管理用户
- clusterAdmin:可以管理整个集群
1.5.3 第一步:连接到MongoDB
使用MongoDB Shell连接
# 连接到本地MongoDB(默认端口27017)
mongosh
# 连接到远程MongoDB
mongosh --host 192.168.1.100 --port 27017
# 连接到特定数据库,例如我这里的myapp
mongosh --host localhost --port 27017 --db myapp
1.5.3.1 连接后的基本操作
// 查看当前数据库
db
// 查看所有数据库
show dbs
// 切换到指定数据库
use myapp
// 查看当前数据库的所有集合
show collections
1.5.4 第二步:创建第一个用户
1.5.4.1 创建管理员用户
首先创建一个超级管理员用户,这个用户可以管理所有数据库:
// 切换到admin数据库
use admin
// 创建管理员用户
db.createUser({
user: "admin",
pwd: "admin123",
roles: [
{ role: "userAdminAnyDatabase", db: "admin" },
{ role: "readWriteAnyDatabase", db: "admin" },
{ role: "dbAdminAnyDatabase", db: "admin" }
]
})
解释:
user
: 用户名pwd
: 密码roles
: 角色数组,每个角色包含:role
: 角色名称db
: 该角色适用的数据库
1.5.4.2 创建应用程序用户
为应用程序创建专用用户:
// 切换到应用程序数据库
use myapp
// 创建应用程序用户
db.createUser({
user: "appuser",
pwd: "app123",
roles: [
{ role: "readWrite", db: "myapp" },
{ role: "read", db: "reports" }
]
})
1.5.4.3 创建只读用户
为报表系统创建只读用户:
// 创建只读用户
db.createUser({
user: "readonly",
pwd: "read123",
roles: [
{ role: "read", db: "myapp" },
{ role: "read", db: "reports" }
]
})
1.5.5 第三步:启用身份验证
1.5.5.1 方法一:命令行启动时启用
# 启动MongoDB并启用认证
mongod --auth --dbpath /data/db
1.5.5.2 方法二:配置文件方式
创建配置文件 mongod.conf
:
# 存储配置
storage:
dbPath: /var/lib/mongodb
# 网络配置
net:
port: 27017
bindIp: 127.0.0.1
# 安全配置
security:
authorization: enabled
使用配置文件启动:
mongod --config /etc/mongod.conf
重启 MongoDB 服务
sudo systemctl restart mongod
1.5.6 第四步:使用用户身份连接
1.5.6.1 连接到MongoDB并认证
# 连接到MongoDB
mongosh --host localhost --port 27017
# 在shell中进行认证
use admin
db.auth("admin", "admin123")
1.5.6.2 直接使用认证信息连接
# 使用管理员用户连接
mongosh --host localhost --port 27017 -u "admin" -p "admin123" --authenticationDatabase "admin"
# 使用应用程序用户连接
mongosh --host localhost --port 27017 -u "appuser" -p "app123" --authenticationDatabase "myapp"
1.5.7 第五步:用户管理操作
1.5.7.1 查看所有用户
// 查看当前数据库的所有用户
db.getUsers()
// 查看特定用户
db.getUser("appuser")
1.5.7.2 修改用户信息
// 修改用户密码
db.changeUserPassword("appuser", "newpassword123")
// 更新用户角色
db.updateUser("appuser", {
roles: [
{ role: "readWrite", db: "myapp" },
{ role: "read", db: "reports" },
{ role: "read", db: "analytics" }
]
})
1.5.7.3 删除用户
// 删除用户
db.dropUser("readonly")
1.5.8 实际应用场景
1.5.8.1 场景一:Web应用程序
// 为Web应用创建用户
use webapp
db.createUser({
user: "webuser",
pwd: "web123",
roles: [
{ role: "readWrite", db: "webapp" }
]
})
// 应用程序连接字符串
// mongodb://webuser:web123@localhost:27017/webapp
1.5.8.2 场景二:数据分析系统
// 为数据分析创建只读用户
use analytics
db.createUser({
user: "analyst",
pwd: "analyst123",
roles: [
{ role: "read", db: "analytics" },
{ role: "read", db: "reports" }
]
})
1.5.8.3 场景三:多租户系统
// 为每个租户创建独立用户
use tenant1
db.createUser({
user: "tenant1_user",
pwd: "tenant1_pass",
roles: [
{ role: "readWrite", db: "tenant1" }
]
})
use tenant2
db.createUser({
user: "tenant2_user",
pwd: "tenant2_pass",
roles: [
{ role: "readWrite", db: "tenant2" }
]
})
1.5.9 高级用户管理
1.5.9.1 创建自定义角色
// 创建自定义角色
use admin
db.createRole({
role: "dataAnalyst",
privileges: [
{
resource: { db: "analytics", collection: "" },
actions: ["find", "aggregate"]
}
],
roles: []
})
// 为用户分配自定义角色
use analytics
db.grantRolesToUser("analyst", [
{ role: "dataAnalyst", db: "admin" }
])
db.grantRolesToUser()
是 MongoDB 中用于为已有用户分配角色的命令,作用是向指定用户授予新的权限角色,从而扩展该用户的操作权限。其中:
- 第一个参数 “analyst” 是目标用户名(即要给哪个用户分配角色)。
- 第二个参数是角色数组,这里指定了要授予的角色:
role: "dataAnalyst"
:要分配的自定义角色名称(之前在 admin 数据库中创建的角色)。
db: "admin"
:该角色的所属数据库(因为 dataAnalyst 是在 admin 数据库中创建的,必须明确指定来源)。
1.5.9.2 用户权限验证
// 检查用户权限
db.runCommand({
usersInfo: "appuser",
showPrivileges: true
})
1.5.10 完整示例:搭建安全的MongoDB环境
步骤1:启动MongoDB
# 启动MongoDB(开发环境)
mongod --dbpath ./data --port 27017
步骤2:创建管理员用户
// 连接到MongoDB
mongosh
// 创建管理员用户
use admin
db.createUser({
user: "admin",
pwd: "admin123",
roles: [
{ role: "userAdminAnyDatabase", db: "admin" },
{ role: "readWriteAnyDatabase", db: "admin" },
{ role: "dbAdminAnyDatabase", db: "admin" }
]
})
步骤3:启用认证并重启
# 停止MongoDB
# Ctrl+C 或 pkill mongod
# 启用认证启动
mongod --auth --dbpath ./data --port 27017
步骤4:创建应用程序用户
// 使用管理员身份连接
mongosh -u "admin" -p "admin123" --authenticationDatabase "admin"
// 创建应用程序数据库和用户
use myapp
db.createUser({
user: "appuser",
pwd: "app123",
roles: [
{ role: "readWrite", db: "myapp" }
]
})
// 测试应用程序用户
use myapp
db.auth("appuser", "app123")
步骤5:测试连接
// 插入测试数据
db.users.insertOne({
name: "张三",
email: "zhangsan@example.com",
created_at: new Date()
})
// 查询数据
db.users.find()
1.6 连接
使用 MongoDB shell 来连接 MongoDB 服务器,标准的 URI 连接语法:
mongodb://[username:password@]host1[:port1][,...hostN[:portN]][/[defaultauthdb][?options]]
mongodb://
:协议头,表示使用 MongoDB。[username:password@]
:(可选)认证信息,包括用户名和密码。host1[:port1][,...hostN[:portN]]
:服务器地址和端口,可以是一个或多个 MongoDB 服务器的地址和端口。/[defaultauthdb]
:(可选)默认认证数据库。[?options]
:(可选)连接选项。
标准的连接格式包含了多个选项(options),如下所示:
authSource
:指定认证数据库。replicaSet
:指定副本集的名称。ssl
:启用 SSL 连接(true 或 false)。readPreference
:指定读偏好,如 primary, primaryPreferred, secondary, secondaryPreferred, nearest。connectTimeoutMS
:指定连接超时时间(毫秒)。socketTimeoutMS
:指定套接字超时时间(毫秒)。
一些示例:
连接到本地 MongoDB 实例(默认端口 27017):
mongodb://localhost
连接到本地 MongoDB 实例,指定数据库:
mongodb://localhost/mydatabase
使用用户名和密码连接到本地 MongoDB 实例:
mongodb://username:password@localhost/mydatabase
连接到远程 MongoDB 实例:
mongodb://remotehost:27017
连接到副本集(Replica Set):
mongodb://host1:27017,host2:27017,host3:27017/mydatabase?replicaSet=myReplicaSet
使用 SSL 连接到 MongoDB:
mongodb://username:password@localhost:27017/mydatabase?ssl=true
使用多个选项连接:
mongodb://username:password@localhost:27017/mydatabase?authSource=admin&ssl=true
1.7 实际应用示例
1.7.1 用户管理系统
// 1. 切换到(或创建)名为"userManagement"的数据库
// 如果该数据库不存在,会在首次插入数据时自动创建
use userManagement
// 2. 向"users"集合中插入一条用户文档
// "users"集合会在首次插入时自动创建
db.users.insertOne({
"username": "zhangsan", // 用户名(唯一标识,字符串类型)
"email": "zhangsan@example.com", // 邮箱(字符串类型)
"profile": { // 个人资料(嵌套文档,存储复杂信息)
"firstName": "张", // 名
"lastName": "三", // 姓
"age": 25, // 年龄(数字类型)
"location": "北京" // 所在地(字符串类型)
},
"roles": ["user", "editor"], // 角色(数组类型,用户可拥有多个角色)
"created_at": new Date(), // 创建时间(Date类型,自动生成当前时间)
"isActive": true // 账号状态(布尔类型,true表示激活)
})
// 3. 查询指定用户的信息
// findOne():返回符合条件的第一个文档
// 查询条件:用户名(username)为"zhangsan"
db.users.findOne({"username": "zhangsan"})
// 4. 更新用户信息
// updateOne():更新符合条件的第一个文档
db.users.updateOne(
{"username": "zhangsan"}, // 更新条件:匹配用户名"zhangsan"的文档
{"$set": {"profile.age": 26}} // 更新操作:$set操作符用于修改指定字段的值
// 这里将嵌套文档profile中的age字段从25更新为26
)
1.7.2 博客系统
// 1. 向博客文章集合(posts)中插入一篇博客文章文档
// 集合(posts)会在首次插入文档时自动创建
db.posts.insertOne({
"title": "MongoDB入门指南", // 博客标题(字符串类型)
"content": "MongoDB是一个文档型数据库...", // 博客正文内容(字符串类型)
"author": "张三", // 作者名称(字符串类型)
"tags": ["数据库", "MongoDB", "教程"], // 标签(数组类型,存储多个字符串)
"comments": [ // 评论列表(数组类型,存储嵌套文档)
{
"user": "李四", // 评论用户
"content": "写得很好!", // 评论内容
"created_at": new Date() // 评论时间(Date类型,自动生成当前时间)
}
],
"published_at": new Date(), // 发布时间(Date类型,自动生成当前时间)
"viewCount": 0 // 阅读量(数字类型,初始为0)
})
// 2. 向指定博客文章添加新评论
// 使用updateOne方法更新文档,通过$push操作符向数组添加元素
db.posts.updateOne(
{"title": "MongoDB入门指南"}, // 更新条件:匹配标题为"MongoDB入门指南"的文档
{"$push": { // $push操作符:向数组字段添加新元素(不覆盖原有元素)
"comments": { // 目标数组字段:comments(评论列表)
"user": "王五", // 新评论的用户
"content": "学习了!", // 新评论的内容
"created_at": new Date() // 新评论的时间(当前时间)
}
}}
)
// 执行后,该博客的comments数组会包含两条评论:李四和王五的评论