> 技术文档 > MongoDB系列教程-第一章:MongoDB简介、安装 、概念解析、用户管理、连接、实际应用示例

MongoDB系列教程-第一章:MongoDB简介、安装 、概念解析、用户管理、连接、实际应用示例

📖 第一章:MongoDB简介、安装 、概念解析、用户管理、连接、实际应用示例

文章目录

    • 1.1 MongoDB简介
    • 1.2 Mongo安装
      • 1.2.1 MongoDB-Windows安装
      • 1.2.2 MongoDB-Linux安装
      • 1.2.3 MongoDB-Mac安装
    • 1.3 MongoDB Shell安装
    • 1.4 MongoDB概念解析
      • 1.4.1 基础概念
      • 1.4.2 数据库
      • 1.4.3 文档(Document) - 数据的核心
      • 1.4.4 集合(Collection) - 文档的容器
      • 1.4.5 数据类型详解
        • 1.4.5.1 ObjectId - 自动生成的主键
        • 1.4.5.2 Date - 日期时间
        • 1.4.5.3 其它特殊类型
    • 1.5 用户管理
      • 1.5.1 用户和数据库的关系
      • 1.5.2 角色(Roles)的概念
      • 1.5.3 第一步:连接到MongoDB
        • 1.5.3.1 连接后的基本操作
      • 1.5.4 第二步:创建第一个用户
        • 1.5.4.1 创建管理员用户
        • 1.5.4.2 创建应用程序用户
        • 1.5.4.3 创建只读用户
      • 1.5.5 第三步:启用身份验证
        • 1.5.5.1 方法一:命令行启动时启用
        • 1.5.5.2 方法二:配置文件方式
      • 1.5.6 第四步:使用用户身份连接
        • 1.5.6.1 连接到MongoDB并认证
        • 1.5.6.2 直接使用认证信息连接
      • 1.5.7 第五步:用户管理操作
        • 1.5.7.1 查看所有用户
        • 1.5.7.2 修改用户信息
        • 1.5.7.3 删除用户
      • 1.5.8 实际应用场景
        • 1.5.8.1 场景一:Web应用程序
        • 1.5.8.2 场景二:数据分析系统
        • 1.5.8.3 场景三:多租户系统
      • 1.5.9 高级用户管理
        • 1.5.9.1 创建自定义角色
        • 1.5.9.2 用户权限验证
      • 1.5.10 完整示例:搭建安全的MongoDB环境
        • 步骤1:启动MongoDB
        • 步骤2:创建管理员用户
        • 步骤3:启用认证并重启
        • 步骤4:创建应用程序用户
        • 步骤5:测试连接
    • 1.6 连接
    • 1.7 实际应用示例
      • 1.7.1 用户管理系统
      • 1.7.2 博客系统

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优势总结

  1. 灵活的数据结构:不需要预定义表结构
  2. JSON格式存储:天然支持复杂的嵌套数据
  3. 水平扩展:容易分布式部署
  4. 强大的查询能力:支持复杂的聚合操作

1.2 Mongo安装

1.2.1 MongoDB-Windows安装

从 MongoDB 官网下载安装,MongoDB 预编译二进制包下载地址:https://www.mongodb.com/try/download/community

MongoDB系列教程-第一章:MongoDB简介、安装 、概念解析、用户管理、连接、实际应用示例

下载 .msi 文件,下载后双击该文件,按操作提示安装即可。

安装过程:

MongoDB系列教程-第一章:MongoDB简介、安装 、概念解析、用户管理、连接、实际应用示例
MongoDB系列教程-第一章:MongoDB简介、安装 、概念解析、用户管理、连接、实际应用示例

MongoDB系列教程-第一章:MongoDB简介、安装 、概念解析、用户管理、连接、实际应用示例
MongoDB系列教程-第一章:MongoDB简介、安装 、概念解析、用户管理、连接、实际应用示例

MongoDB系列教程-第一章:MongoDB简介、安装 、概念解析、用户管理、连接、实际应用示例
点击Next,默认勾选MongoDB Compass,MongoDB Compass是MongoDB官方推出的图形化用户界面(GUI)工具,专为简化MongoDB数据库的管理、查询和分析而设计。它提供了直观的可视化界面,用户无需编写复杂的命令行代码,就能轻松完成数据库连接、集合(Collection)浏览、文档(Document)增删改查、索引管理、数据导入导出等操作。同时,它还具备实时性能监控、查询性能分析等功能,帮助开发者和数据库管理员更高效地调试和优化MongoDB数据库,尤其适合初学者快速上手MongoDB,或用于日常开发中的数据管理工作。我这里直接默认安装。
MongoDB系列教程-第一章:MongoDB简介、安装 、概念解析、用户管理、连接、实际应用示例

MongoDB系列教程-第一章:MongoDB简介、安装 、概念解析、用户管理、连接、实际应用示例

MongoDB系列教程-第一章:MongoDB简介、安装 、概念解析、用户管理、连接、实际应用示例
至此,安装完成,安装成功后可以在任务管理器服务里看的MongoDB服务:

MongoDB系列教程-第一章: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系列教程-第一章:MongoDB简介、安装 、概念解析、用户管理、连接、实际应用示例
MongoDB系列教程-第一章:MongoDB简介、安装 、概念解析、用户管理、连接、实际应用示例
MongoDB系列教程-第一章:MongoDB简介、安装 、概念解析、用户管理、连接、实际应用示例

来到 MongoDB Shell安装目录中,双击其中的mongosh.exe,会显示Please enter a MongoDB connection string (Default: mongodb://localhost/):的字样。

MongoDB系列教程-第一章:MongoDB简介、安装 、概念解析、用户管理、连接、实际应用示例
MongoDB系列教程-第一章:MongoDB简介、安装 、概念解析、用户管理、连接、实际应用示例
意在让你输入连接 MongoDB 数据库的连接字符串(如默认的 mongodb://localhost/ 就是连接本地 MongoDB 的字符串,保持默认可以直接回车),这里输入的字符串会被优先解析为完整的连接字符串(用于指定服务器地址、端口等连接信息),而非单纯的服务器名或数据库名。连接字符串的格式通常是 mongodb://:/,其中:

  • : 用于指定服务器地址和端口(如 localhost:27017);
  • 末尾的 可选,用于指定连接后默认进入的数据库(若不指定,默认进入 test 数据库)。
    MongoDB系列教程-第一章:MongoDB简介、安装 、概念解析、用户管理、连接、实际应用示例
    如果输入的是非标准连接字符串的普通字符串(如随便输入 abc),mongosh 会尝试按以下规则解析:
  1. 先假设这是一个简化的连接字符串,默认补充服务器地址为 localhost:27017,形成 mongodb://localhost:27017/abc
  2. 此时,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 指令启动工具,再附加连接参数。

  • 其中 是 MongoDB 服务器的主机名或 IP 地址
  • 是 MongoDB 服务器的端口号

查看版本的话,命令行可以直接输入mongosh --version来查看。
MongoDB系列教程-第一章:MongoDB简介、安装 、概念解析、用户管理、连接、实际应用示例

进入数据库后,可以执行各种 MongoDB 数据库操作(这些操作后面会详细讲述):

  • 查看当前数据库:db
  • 显示数据库列表:show dbs
  • 切换到指定数据库:use
  • 执行查询操作:db..find()
  • 插入文档:db..insertOne({ ... })
  • 更新文档:db..updateOne({ ... })
  • 删除文档:db..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 dbsadmin 0.000GBlocal 0.000GBtest 0.000GB// 查看当前使用的数据库> dbtest// 切换到指定数据库> use mydatabaseswitched to db mydatabase

数据库命名规则:

  • 不能为空字符串
  • 不能包含空格、点号、美元符号、斜杠、反斜杠
  • 全部小写
  • 最多64个字符

特殊数据库:

  • admin:管理员数据库,拥有所有权限
  • local:本地数据库,不会被复制
  • config:分片配置数据库

特殊数据库的详细介绍:

  1. admin 数据库:这是MongoDB的\"超级管理员\"数据库,相当于系统的root用户。在这里创建的用户自动获得所有数据库的管理权限,可以执行关键的服务器管理命令如关闭服务器、列出所有数据库等。它包含重要的系统集合,在生产环境中只允许数据库管理员访问。
  2. local 数据库:这是一个特殊的本地数据库,其数据永远不会被复制到其他服务器。它适合存储本地服务器特有的数据,如本地日志、临时数据、服务器配置等。在副本集环境中特别有用,因为每个节点可以存储自己特有的信息,不会影响副本集同步性能。
  3. config 数据库这是分片集群架构的核心组件,专门存储分片集群的元数据和配置信息。它包含多个重要集合,记录分片服务器信息、数据库配置、分片键信息、数据块分布等。整个分片集群的所有组件都需要访问它来获取配置信息,因此其高可用性对整个集群至关重要。

1.4.3 文档(Document) - 数据的核心

文档是MongoDB的基本数据单元,本质上是JSON格式的数据。每个文档可以有不同的结构,这是MongoDB最大的特点。
例如下图中的两个文档:
MongoDB系列教程-第一章: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 collectionsusersproducts// 查看集合中的文档数量> 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类型。

MongoDB系列教程-第一章:MongoDB简介、安装 、概念解析、用户管理、连接、实际应用示例

// 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() //格林尼治时间> mydate1ISODate(\"2018-03-04T14:58:51.233Z\")> typeof mydate1object
> var mydate2 = ISODate() //格林尼治时间> mydate2ISODate(\"2018-03-04T15:00:45.479Z\")> typeof mydate2object

这样创建的时间是日期类型,需要返回一个时间类型的字符串,可以:

> var mydate1str = mydate1.toString()> mydate1strSun Mar 04 2018 14:58:51 GMT+0000 (UTC) > typeof mydate1strstring

或者

> 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 admindb.createUser({ user: \"admin\", pwd: \"admin123\", roles: [\"userAdminAnyDatabase\", \"readWriteAnyDatabase\"]})// 在myapp数据库中创建用户use myappdb.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# 连接到远程MongoDBmongosh --host 192.168.1.100 --port 27017# 连接到特定数据库,例如我这里的myappmongosh --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并认证
# 连接到MongoDBmongosh --host localhost --port 27017# 在shell中进行认证use admindb.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 webappdb.createUser({ user: \"webuser\", pwd: \"web123\", roles: [ { role: \"readWrite\", db: \"webapp\" } ]})// 应用程序连接字符串// mongodb://webuser:web123@localhost:27017/webapp
1.5.8.2 场景二:数据分析系统
// 为数据分析创建只读用户use analyticsdb.createUser({ user: \"analyst\", pwd: \"analyst123\", roles: [ { role: \"read\", db: \"analytics\" }, { role: \"read\", db: \"reports\" } ]})
1.5.8.3 场景三:多租户系统
// 为每个租户创建独立用户use tenant1db.createUser({ user: \"tenant1_user\", pwd: \"tenant1_pass\", roles: [ { role: \"readWrite\", db: \"tenant1\" } ]})use tenant2db.createUser({ user: \"tenant2_user\", pwd: \"tenant2_pass\", roles: [ { role: \"readWrite\", db: \"tenant2\" } ]})

1.5.9 高级用户管理

1.5.9.1 创建自定义角色
// 创建自定义角色use admindb.createRole({ role: \"dataAnalyst\", privileges: [ { resource: { db: \"analytics\", collection: \"\" }, actions: [\"find\", \"aggregate\"] } ], roles: []})// 为用户分配自定义角色use analyticsdb.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:创建管理员用户
// 连接到MongoDBmongosh// 创建管理员用户use admindb.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 myappdb.createUser({ user: \"appuser\", pwd: \"app123\", roles: [ { role: \"readWrite\", db: \"myapp\" } ]})// 测试应用程序用户use myappdb.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数组会包含两条评论:李四和王五的评论