目标: 了解什么是关系型数据库
关系型数据库,是指采用了 关系模型 来组织数据的数据库。
关系模型,指的就是 二维表格模型,而一个关系型数据库就是由 二维表及其之间的联系 所组成的一个数据组织。
关系型数据库一般都支持数据库事务,必须具备 ACID
特性。ACID
分别是指:
Atomic
原子性 (事务操作要么全做完,要么都不做)Consistency
一致性 (数据库要一直处于一致的状态 => 完整性约束: a + b = 10)Isolation
隔离性 (并发的事务之间不会互相影响)Durability
持久性 (一旦事务提交, 修改将永久保存)优点
缺点
IO瓶颈 :
网站并发性通常非常高(每秒上万次读写),硬盘I/O
是一个很大的瓶颈
效率低下:
网站数据量是巨大,关系型数据库,查询效率是非常低的
难以横向扩展:
没有办法像web server
和 app server
那样通过添加硬件和服务节点来扩展性能和负载能力。
当需要进行升级和扩展时,往往需要停机维护和数据迁移。
关系型数据库, 比较适合存储持久化的一些数据, 关系复杂的结构数据. 数据量特别大, 实时性要求高 =>非关系型
流行的关系型数据库
了解什么是非关系型数据库
非关系型数据库,是指非关系型的、分布式的、且一般不保证遵循 ACID
原则的数据存储系统。
非关系型数据库以键值对存储,且结构不固定,每一个元组可以有不一样的字段,每个元组可以根据需要增加一些自己的键值对,不局限于固定的结构,可以减少一些时间和空间的开销。
优点
格式灵活:可以是:key-value 形式、文档形式、图片形式等,灵活, 应用场景广泛
用户可以根据需要去添加自己需要的字段,为了获取用户的不同信息,无需多表进行关联查询。
仅需要根据 id
取出相应的 value
就可以完成查询
适用于SNS社交网络服务中,例如 Facebook、微博等。
系统升级、功能增加等场景,往往意味着需要对数据结构的巨大变动,关系型数据库难以应付这一点
速度快:NoSQL 可以使用硬盘或者随机存储器作为载体,而关系型数据库只能使用硬盘
高扩展性
成本低:NoSQL 数据库部署简单,且基本都是开源免费软件
缺点
流行的非关系型数据库
非关系型数据库的分类
虽然 NoSQL 数据库有很多,但是它们的功能也是有所差异的,在解决问题方面有所侧重。
因此 NoSQL 一般分为以下几类:
Redis 介绍 (缓存)
Redis 是完全开源的,遵守 BSD 协议,是一个高性能的 key-value 数据库。
Redis 的优势:
MongoDB 介绍 (可扩展高性能, 结构可变的数据存储方案)
MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。在高负载的情况下,添加更多的节点,可以保证服务器性能。MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。
MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。
安装 Redis,以及对 Redis 的基本功能的使用
安装
Redis 的安装文件下载地址:https://github.com/tporadowski/redis/releases
安装完成后,可以运行 redis-server.exe 启动 Redis 服务器。 (安装, 一直下一步即可)
数据操作
运行 redis-cli.exe,打开 Redis 的命令行客户端。
操作一:向 Redis 中存储一个字符串键值对
set key1 hello # 存入一个键值对,键为 key,值为字符串 hello
操作二:从 Redis 中获取某个键值对值
get key1 # 得到字符串 hello
操作三:查看 Redis 中所有的键值对 key
keys *
操作四:向 Redis 中设置一个数字并自增
incr mynum # mynum 为 1
incr mynum # mynum 为 2
get mynum # 查看 mynum 结果为 2
【更多操作参考操作命令手册】
掌握从 Koa 代码中连接 Redis 服务器并操作 Redis 中的数据
使用步骤
目前主流的 Node.js 的 Redis 驱动包有两个:node-redis 和 ioredis,这两个包都有性能非常高、使用方便的特点。而后者的性能更好、功能更强大。
npm i ioredis
const Koa = require('koa')
// 1. 引入 ioredis
const Redis = require('ioredis')
// 2. 创建 Redis 客户端实例,指定要连接的 Redis 服务器
const redis = new Redis({
port: 6379, // redis 服务器的默认端口
host: '127.0.0.1' // redis 服务器的 IP 地址
})
const app = new Koa()
app.use(async ctx => {
// 通过客户端实例,向 Redis 服务器发送数据操作命令,进行相关操作
//(这等价于在命令行窗口中输入命令进行操作)
// 1) 设置数据
await redis.set('my_key1', 'hello,world')
await redis.set('my_key2', 'foo,bar')
await redis.incr('my_num')
// 2) 获取数据
const myKey1Value = await redis.get('my_key1')
console.log(myKey1Value)
ctx.body = '完成'
})
app.listen(3000)
掌握 MongoDB 服务器软件的安装和启动
安装
MongoDB下载地址:https://www.mongodb.com/try/download/community
下载安装好以后,启动 MongoDB 服务器:
mongod --dbpath=C:\data\db
# mongod 为 MongoDB 的服务器程序
# 数据文件目录默认为 /data/db
验证
MongoDB 服务器启动后,访问 http://localhost:27017,如果出现这样的结果则表示已经成功:
命令演示:
show dbs 查看数据库
db 查看当前数据库
use database 切换数据库
show collections 查看集合列表
…
插入数据演示:
db.users.insert({ name: 'Jack', age: 18 })
检索查看数据:
db.users.find()
MongoDB中的数据存储结构:
MongoDB是文档型数据库, 存储的都是一些 JSON 格式数据
{
// 数据库 database
"test1": {
// 集合 collection
"users": [
// 文档 document
{
// 数据字段 field
"id": 1,
"username": "小明",
"password": "123456"
},
{
"id": 2,
"username": "小王",
"password": "123456",
"desc": "不错"
}
// ...
],
"teachers": [
{
"id": 1,
"name": "李老师"
},
{
"id": 2,
"name": "王老师",
}
]
},
// 数据库
"test2": {}
// ...
}
show dbs
db
use 数据库名
db.dropDatabase()
db.集合名.insert({ name: 'zs', age: 18 })
show collections
db.集合名称.drop()
MongoDB 将数据记录存储为 BSON 文档
BSON(Binary JSON)是 JSON 文档的二进制表示形式,它比 JSON 包含更多的数据类型
BSON 规范
字段名称 _id
保留用作主键;它的值在集合中必须是唯一的,不可变的,并且可以是数组以外的任何类型。
> db.users.find()
{ "_id" : ObjectId("619cc474cc1980baa07f2c24"), "name" : "Jack", "age" : 18 }
可视化操作工具:
db.集合名.insertOne({ ... }) 插入一个
db.集合名.insertMany([{ ... }, { ... }]) 插入多个
db.集合名.insert({ ... }) 插入一个或多个
db.集合名.find() 查询所有
db.集合名.find().pretty() 查询并格式化
db.集合名.find(查询条件, { 键: 0/1 }) 0表示排除, 1表示包含
相等条件
db.集合名.find({
键: 值
})
AND 条件
其他查询运算符: https://docs.mongodb.com/manual/reference/operator/query-comparison/
db.集合名.find({
键: 值,
键: 值,
键: {
$lt: 值
},
键: /\d/
})
OR 条件
db.集合名.find({
$or: [
{ 键: 值 },
{ 键: 值 }
]
})
// 更新第一个满足条件的项
db.集合名.updateOne(查询条件, {
$set: {
键: 值,
键: 值
}
})
// 更新所有满足条件的项
db.集合名.updateMany(查询条件, {
$set: {
键: 值,
键: 值
}
})
db.collection.deleteMany(查询条件)
db.collection.deleteOne(查询条件)
掌握从 Koa 代码中连接 MongoDB 服务器,并简单往 MongoDB 中插入一条数据
mongodb 是官方提供的 Node.js 驱动包,可以连接 MongoDB 服务器,并通过发送命令来实现对 MongoDB 服务器的各种操作。
yarn add mongodb koa @koa/router
// 1. 引入 mongodb 驱动包
const mongodb = require('mongodb')
const MongoClient = mongodb.MongoClient
// 2. 创建 MongoDB 客户端实例
// MongoDB 服务器的连接地址,其中可包含用户名、密码、域名、端口、数据库名等信息
const mongoClient = new MongoClient('mongodb://127.0.0.1:27017')
// 3. 建立连接
mongoClient.connect()
// 4. 连接关联哪个数据库
const db = mongoClient.db('classroom')
module.exports = db
const Router = require('@koa/router')
const router = new Router()
router.get('/', async ctx => {
ctx.body = '这是首页'
})
router.get('/list', async ctx => {
ctx.body = '这是列表'
})
module.exports = router
const Koa = require('koa')
const router = require('./router')
const app = new Koa()
app.use(router.routes())
app.listen(8888, () => console.log('服务器启动成功...'))
const Router = require('@koa/router')
const db = require('./db')
const router = new Router()
router.get('/', async ctx => {
ctx.body = '这是首页'
})
router.get('/list', async ctx => {
ctx.body = '这是列表'
})
router.get('/add', async ctx => {
const collection = db.collection('students')
const info = await collection.insertOne({ name: 'Tom', age: 18 })
console.log(info)
collection.find().forEach(item => {
console.log(item)
})
ctx.body = '操作完成'
})
module.exports = router
掌握从 Koa 代码中对 MongoDB 的数据做增、删、改、查操作
新增数据
向 MongoDB 中的某个 collection 内新增一条或多条数据,可以使用以下方法:
// 新增一条
await collection.insertOne({ name: 'Tom', age: 18 })
// 新增多条
await collection.insertMany([
{ name: 'Jack', age: '28' },
{ name: 'Marray', age: '21' },
])
默认情况下,新增后的每条数据都会自动被添加上一个:类型为 ObjectID、字段名为 _id
的唯一标识。
删除数据
要删除某个 collection 中的指定 _id
数据,可以使用:
const mongodb = require('mongodb')
const ObjectID = mongodb.ObjectID
collection.deleteOne(
// 查询条件
{
_id: ObjectID('....ID的值.....')
}
)
修改数据
如果要对某个 collection 中的某些数据进行更新,可以使用 updateOne
或 updateMany
方法:
await collection.updateOne(
// 查询条件
{
_id: ObjectID('60bc8eb33e941a0a20875e0d')
},
// 更新表达式选项
{
$set: { name: '张三' }
}
)
查询数据
将某些符合查询条件的数据从 collection 中查找出来,可以使用 find
方法:
const users = await collection.find(
// 查询条件
{
// age 字段值 大于 15
age: {
$gt: 15
}
}
)
查询结果为游标类型(Cursor),不能直接用 for 循环等遍历,可以使用它的 forEach
方法遍历,或先将它转为数组:
// 用 forEach 方法遍历
users.forEach(user => {
console.log(user);
})
// 先转为数组后再用 for 循环遍历
const arr = await users.toArray()
for (const item of arr) {
console.log(item)
}
查看目前MongoDB中的所有用户
use admin
show users
db.createUser({ user: 'root', pwd: '123456', roles: ["root"]})
重新打开cmd,在mongodb路径的bin目录下,执行
mongod --dbpath=C:\data\db --auth (data是安装mongodb创建的数据库文件夹)