【实战介绍】
本次课程是MongoDB实战课程的第一部分"MongoDB基础入门"中的第一个章节。作为整个课程的起点,我们将介绍MongoDB的基本概念,包括数据库、集合和文档。这些是理解和使用MongoDB的基础知识,为后续学习打下坚实基础。
本节课程主要讲解:
-
MongoDB的核心概念及其与传统关系型数据库的区别
-
MongoDB的数据组织结构:数据库、集合和文档
-
MongoDB文档的基本特性和结构
-
实际操作MongoDB基本环境并创建数据库、集合和文档
学习MongoDB基本概念的价值在于:它是NoSQL数据库的代表作,采用文档存储模式,能更自然地表达数据,并提供高性能、高可用性和易扩展性,适合处理大规模、结构复杂且变化频繁的数据。
【实战任务内容】
1. MongoDB简介
MongoDB是一个开源、分布式的文档数据库,由C++语言编写,旨在为Web应用提供可扩展的高性能数据存储解决方案。它属于NoSQL(Not Only SQL)数据库,不使用传统的表-行模式,而采用灵活的文档模型。
示例:如果要存储用户信息,在关系型数据库中可能需要创建"用户"、"地址"、"订单"等多个表,而在MongoDB中,可以将所有相关信息存储在一个文档中,减少了连接操作。
2. MongoDB与关系型数据库的区别
传统关系型数据库和MongoDB在概念和术语上有明显差异:
关系型数据库 | MongoDB | 说明 |
---|---|---|
数据库(Database) | 数据库(Database) | 概念相同 |
表(Table) | 集合(Collection) | 集合是文档的容器 |
行(Row) | 文档(Document) | 文档采用BSON格式 |
列(Column) | 字段(Field) | 字段是键值对 |
主键(Primary Key) | _id字段 | MongoDB自动创建_id作为主键 |
表连接(Join) | 嵌入文档和引用 | MongoDB使用嵌入或引用代替连接 |
示例:在MySQL中可能有一个users表,而在MongoDB中,会有一个users集合。
3. MongoDB的数据组织结构
MongoDB采用三层结构组织数据:
3.1 数据库(Database)
数据库是集合的容器,一个MongoDB服务器通常有多个数据库。
-
每个数据库有自己的文件集
-
不同数据库存储在不同的文件中
-
默认数据库为"test"
示例:一个应用可能有"用户数据库"、"产品数据库"和"订单数据库"。
3.2 集合(Collection)
集合是MongoDB文档的分组,相当于关系型数据库中的表。
-
集合存在于数据库中
-
集合没有固定的结构
-
同一集合中的文档可以有不同的字段
-
同一集合中文档的字段可以有不同的数据类型
示例:在用户数据库中,可能有"普通用户"、"管理员"等不同的集合。
3.3 文档(Document)
文档是MongoDB中数据的基本单位,由键值对组成。
-
文档存储为BSON(二进制JSON)格式
-
文档中的字段顺序与存储顺序有关
-
MongoDB的文档不需要具有相同的字段集
-
同一集合中的文档可以有不同的字段集
示例:一个用户文档可能如下:
{
"_id": ObjectId("60a67c8d1f0e896543210bc3"),
"name": "张三",
"age": 28,
"email": "zhangsan@example.com",
"address": {
"city": "北京",
"postcode": "100000"
},
"hobbies": ["读书", "旅游", "摄影"]
}
4. MongoDB的文档特性
4.1 文档的唯一标识符(_id)
每个文档都有一个唯一的_id
字段作为主键:
-
如果创建文档时未指定
_id
,MongoDB会自动生成 -
_id
的值在集合中必须唯一 -
默认的
_id
值是一个ObjectId对象,它是一个12字节的BSON类型
示例:ObjectId("507f1f77bcf86cd799439011")由时间戳、机器ID、进程ID和计数器组成。
4.2 文档大小限制
MongoDB对文档有16MB的大小限制,以确保性能和有效索引。对于需要存储更大文档的场景,MongoDB提供了GridFS规范。
示例:存储大型PDF文件时,不应直接存入文档,而应使用GridFS。
4.3 文档字段名称限制
-
字段名不能含有
\0
(空字符) -
不能以
$
开头 -
不能包含
.
字符 -
_id
字段名保留用作主键
示例:{"user.name": "张三"}
是不允许的,但可以使用{"user": {"name": "张三"}}
。
【实战操作】
实战1:安装和启动MongoDB服务
环境初始化
##修改dns
root@ssdevops.com:~$ vi /etc/resolv.conf
##修改或新增dns
nameserver 114.114.114.114
##解锁目录
chattr -ai /etc/passwd /etc/group /etc/shadow /etc/gshadow
在CentOS 7.6上安装MongoDB社区版:
root@ssdevops.com:~$ vi /etc/yum.repos.d/mongodb-org-4.0.repo
添加以下内容:
[mongodb-org-4.0]
name=MongoDB Repository
baseurl=https://mirrors.aliyun.com/mongodb/yum/redhat/7/mongodb-org/4.0/x86_64/
gpgcheck=0
enabled=1
安装MongoDB:
root@ssdevops.com:~$ yum clean all
root@ssdevops.com:~$ yum makecache
root@ssdevops.com:~$ yum install -y mongodb-org
启动MongoDB服务并设置开机自启:
root@ssdevops.com:~$ systemctl start mongod
root@ssdevops.com:~$ systemctl enable mongod
root@ssdevops.com:~$ systemctl status mongod
执行结果截图:
实战2:连接MongoDB服务器
使用MongoDB Shell连接到本地MongoDB服务器:
root@ssdevops.com:~$ mongo
查看当前数据库:
root@ssdevops.com:~$ show dbs
执行结果截图:
实战3:创建和切换数据库
创建并切换到新数据库(在MongoDB中,数据库是隐式创建的):
root@ssdevops.com:~$ use school
查看当前使用的数据库:
root@ssdevops.com:~$ db
注意:新创建的数据库不会显示在数据库列表中,直到它包含至少一个集合。
执行结果截图:
实战4:创建集合
在MongoDB中创建集合有两种方式:
-
显式创建:
root@ssdevops.com:~$ db.createCollection("students")
-
隐式创建(插入文档时自动创建):
root@ssdevops.com:~$ db.teachers.insert({"name": "王老师", "subject": "数学"})
查看当前数据库中的集合:
root@ssdevops.com:~$ show collections
执行结果截图:
实战5:在集合中插入文档
向students集合中插入单个文档:
root@ssdevops.com:~$ db.students.insertOne({
"name": "张三",
"age": 20,
"grade": "大二",
"major": "计算机科学",
"courses": ["数据库", "操作系统", "网络编程"],
"contact": {
"email": "zhangsan@example.com",
"phone": "13800138000"
}
})
向students集合中插入多个文档:
root@ssdevops.com:~$ db.students.insertMany([
{
"name": "李四",
"age": 21,
"grade": "大三",
"major": "软件工程",
"courses": ["数据库", "软件测试", "Web开发"],
"contact": {
"email": "lisi@example.com",
"phone": "13900139000"
}
},
{
"name": "王五",
"age": 19,
"grade": "大一",
"major": "人工智能",
"courses": ["高等数学", "线性代数", "Python编程"],
"contact": {
"email": "wangwu@example.com",
"phone": "13700137000"
}
}
])
执行结果截图:
查看集合中的所有文档:
root@ssdevops.com:~$ db.students.find()
格式化显示结果:
root@ssdevops.com:~$ db.students.find().pretty()
查找特定文档:
root@ssdevops.com:~$ db.students.find({"name": "张三"})
执行结果截图:
实战7:MongoDB数据库配置文件
查看MongoDB的配置文件:
root@ssdevops.com:~$ cat /etc/mongod.conf
主要配置项解释:
# 存储配置
storage:
dbPath: /var/lib/mongo # 数据存储路径
journal:
enabled: true # 启用日志
# 系统日志配置
systemLog:
destination: file # 日志输出到文件
logAppend: true # 追加日志而不是覆盖
path: /var/log/mongodb/mongod.log # 日志文件路径
# 网络配置
net:
port: 27017 # 默认端口
bindIp: 127.0.0.1 # 绑定IP,默认只允许本地连接
修改配置允许远程连接(谨慎操作,生产环境需要设置安全措施):
root@ssdevops.com:~$ vi /etc/mongod.conf
将bindIp: 127.0.0.1
修改为bindIp: 0.0.0.0
,然后重启服务:
root@ssdevops.com:~$ systemctl restart mongod
执行结果截图:
【课后思考】
-
MongoDB文档模型与关系型数据库的表模型相比,在处理复杂数据结构时有哪些优势和劣势?
-
在设计MongoDB集合时,什么情况下应该使用嵌入式文档,什么情况下应该使用引用?
-
MongoDB默认生成的ObjectId有什么特点?它是如何保证唯一性的?
【高频面试题】
面试题1:MongoDB与关系型数据库相比有哪些优缺点?
思路解析: MongoDB的主要优点包括:
-
文档模型更接近于面向对象的程序设计,开发更自然
-
灵活的模式设计,适应快速迭代的业务需求
-
强大的水平扩展能力,适合处理大数据量
-
高性能的读写操作,特别是对于复杂数据的查询
主要缺点包括:
-
不支持像SQL那样复杂的事务机制(虽然新版本有所改进)
-
消耗更多的存储空间(存储结构和索引)
-
不适合需要多表连接的复杂查询场景
-
在某些特定场景下,一致性保证较弱
面试题2:解释MongoDB中的_id字段及其作用
思路解析: _id字段是MongoDB文档的主键,具有以下特性:
-
在集合内必须唯一
-
默认是一个ObjectId对象,也可以指定为其他类型
-
ObjectId是一个12字节的BSON类型,由以下部分组成:
-
4字节:UNIX时间戳(秒)
-
3字节:机器标识符
-
2字节:进程ID
-
3字节:计数器
-
这种设计确保了在分布式系统中生成的ID不会冲突,同时包含了时间信息,便于按时间排序。
在实际应用中,_id的自动生成机制简化了分布式系统的设计,无需中央协调就能生成唯一标识符。