建表

users

columndataTypepk主键nn不为空AI自动增加Default
idintYYY
usernamevarchar(20)Y
passwordvarchar(20)Y
nicknamevarchar(10)Y

blogs

columndataTypepk主键nn不为空AI自动增加Default
idintYYY
titlevarchar(50)Y
contenttextY
useridintY

sequlize

安装插件

1
yarn add mysql2 sequelize -d

创建链接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const Sequelise = require('sequelize')

const conf = {
host: 'localhost',
dialect: 'mysql'
}
// 数据库名、账户名、密码
const seq = new Sequelise('koa2_weibo', 'root', 'root', conf)

// 测试链接

seq
.authenticate()
.then(() => {
console.log('ok')
})
.catch(() => {
console.log('error')
})

创建模型

单独用一个文件用于定义数据库模型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const Sequelize = require('sequelize')
const seq = require('./seq')

// 创建模型

// 数据表的名字时users
const User = seq.define('user', {
// id 会自动创建并设为主键 自增
userName: {
type: Sequelize.STRING,
allowNull: false
},
password: {
type: Sequelize.STRING,
allowNull: false
},
nickName: {
type: Sequelize.STRING
}
})

module.exports = User

模型创建完成后使用同步功能将模型同步到数据库中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const seq = require('./seq')

require('./model')

// 测试链接
seq
.authenticate()
.then(() => {
console.log('ok')
})
.catch(() => {
console.log('error')
})

// 执行同步
seq.sync({ force: true }).then(() => {
console.log('同步成功')
process.exit()
})

创建外键

场景:Blog表中的userId键是User表的id外键。

对于Sequelize来说,有两种创建外键的方式。

1
2
3
4
5
6
7
8
// 外键关联 第一种方式
Blog.belongsTo(User, {
foreignKey: 'userId'
})
// 外键关联 第二种方式
User.hasMany(Blog, {
foreignKey: 'userId'
})

插入数据

插入数据就是新建一条数据。

1
2
3
4
5
6
const zhangsan = await User.create({
userName: 'zhangsan',
password: '123',
nickName: '张三'
})
console.log(zhangsan.dataValues.id)

查询数据

  1. 查询单个数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    const zhangsan = await User.findOne({
    // 查询特定的列
    attributes: ['userName', 'nickName'],
    // 查询条件
    where: {
    userName: 'zhangsan'
    }
    })
    console.log(zhangsan.dataValues)

    通过attributes属性可以限制只返回userNamenickName字段的内容。

    image-20201216144125998

  2. 查询列表

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // 查询一个列表
    const zhangsanBlogList = await Blog.findAll({
    where: {
    userId: 1
    },
    order: [['id', 'desc']]
    })
    console.log(
    'zhangsanBlogList',
    zhangsanBlogList.map((blog) => blog.dataValues)
    )

    通过order属性可以设置排序规则。

    image-20201216144328218

  3. 分页查询

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    const blogPageList = await Blog.findAll({
    // 每次查询2条
    limit: 2,
    // 跳过0条
    offset: 0,
    // 倒序
    order: [['id', 'desc']]
    })
    console.log(
    'blogPageList',
    blogPageList.map((blog) => blog.dataValues)
    )

    image-20201216144714152

  4. 查询总数

    查询数据总量。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    const blogListAndCount = await Blog.findAndCountAll({
    // 每次查询2条
    limit: 2,
    // 跳过0条
    offset: 0,
    // 倒序
    order: [['id', 'desc']]
    })

    console.log(
    'blogListAndCount',
    blogListAndCount.count, // 所有的总数,不考虑分页
    blogListAndCount.rows.map((blog) => blog.dataValues)
    )

    image-20201216145126013

  5. 连表查询

    通过belongsTo定义外键可以使用如下方式进行连表查询。(通过微博查询发起人)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    const blogListWithUser = await Blog.findAndCountAll({
    order: [['id', 'desc']],
    include: [
    {
    model: User,
    attributes: ['userName', 'nickName'],
    where: {
    userName: 'zhangsan'
    }
    }
    ]
    })
    console.log(
    'blogListWithUser',
    blogListWithUser.count,
    blogListWithUser.rows.map((blog) => {
    const blogVal = blog.dataValues
    blogVal.user = blogVal.user.dataValues
    return blogVal
    })
    )

    image-20201216150251353

  6. 连表查询

    通过hasMany定义外键可以使用如下方式进行查询(通过用户名查询发过的微博)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    const userListWithBlog = await User.findAndCountAll({
    attributes: ['userName', 'nickName'],
    include: [{ model: Blog }]
    })
    console.log(
    'userListWithBlog',
    userListWithBlog.count,
    userListWithBlog.rows.map((user) => {
    const userVal = user.dataValues
    userVal.blogs = userVal.blogs.map((blog) => blog.dataValues)
    return userVal
    })
    )

    image-20201216151450433

修改数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// update 传入两个参数
// 第一个参数是需要修改的值
// 第二个参数传入修改的条件
const updateRes = await User.update(
{
nickName: '张三1'
},
{
where: {
username: 'zhangsan'
}
}
)
console.log('updateRes', updateRes)

image-20201216152134143

返回结果为一个数组,元素为修改的行数。1表示修改了一行

删除数据

1
2
3
4
5
6
const delBlogRes = await Blog.destroy({
where: {
id: 4
}
})
console.log('delBlogRes', delBlogRes)

image-20201216153839110

连接池

image-20201216154814172

设置连接池只需要在创建链接的配置中填入pool配置即可

1
2
3
4
5
6
// 连接池
conf.pool = {
max: 5,
min: 0,
idle: 10000
}

redis

安装

1
yarn add redis -d

redis相关操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/**
* @description 链接 redis 的方法 get set
* @author 小康
* @website https://xiaokang.me
*/
const redis = require('redis')

const { REDIS_CONF } = require('../config/db')

// 创建客户端
const redisClient = redis.createClient(REDIS_CONF.prot, REDIS_CONF.host)
redisClient.on('error', (err) => {
console.log('redis error', err)
})

/**
*
* @param {string} key 键
* @param {string} value 值
* @param {number} timeout 超时时间
*/
function set(key, value, timeout = 60 * 60) {
if (typeof value === 'object') {
value = JSON.stringify(value)
}
redisClient.set(key, value)
redisClient.expire(key, timeout)
}
/**
*
* @param {string} key 键
*/
function get(key) {
const promise = new Promise((resolve, reject) => {
redisClient.get(key, (err, val) => {
if (err) {
reject(err)
return
}
if (val == null) {
resolve(null)
}
try {
resolve(JSON.parse(val))
} catch (error) {
resolve(val)
}
})
})
return promise
}

module.exports = { set, get }