建表

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

安装插件

yarn add mysql2 sequelize -d

创建链接

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')
  })

创建模型

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

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

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

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来说,有两种创建外键的方式。

// 外键关联 第一种方式
Blog.belongsTo(User, {
  foreignKey: 'userId'
})
// 外键关联 第二种方式
User.hasMany(Blog, {
  foreignKey: 'userId'
})

插入数据

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

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

查询数据

  1. 查询单个数据

    const zhangsan = await User.findOne({
        // 查询特定的列
        attributes: ['userName', 'nickName'],
        // 查询条件
        where: {
            userName: 'zhangsan'
        }
    })
    console.log(zhangsan.dataValues)

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

    image-20201216144125998

  2. 查询列表

    // 查询一个列表
    const zhangsanBlogList = await Blog.findAll({
        where: {
            userId: 1
        },
        order: [['id', 'desc']]
    })
    console.log(
        'zhangsanBlogList',
        zhangsanBlogList.map((blog) => blog.dataValues)
    )

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

    image-20201216144328218

  3. 分页查询

    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. 查询总数

    查询数据总量。

    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定义外键可以使用如下方式进行连表查询。(通过微博查询发起人)

    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定义外键可以使用如下方式进行查询(通过用户名查询发过的微博)

    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

修改数据

// update 传入两个参数
// 第一个参数是需要修改的值
// 第二个参数传入修改的条件
const updateRes = await User.update(
    {
        nickName: '张三1'
    },
    {
        where: {
            username: 'zhangsan'
        }
    }
)
console.log('updateRes', updateRes)

image-20201216152134143

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

删除数据

const delBlogRes = await Blog.destroy({
    where: {
        id: 4
    }
})
console.log('delBlogRes', delBlogRes)

image-20201216153839110

连接池

image-20201216154814172

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

// 连接池
conf.pool = {
    max: 5,
    min: 0,
    idle: 10000
}

redis

安装

yarn add redis -d

redis相关操作

/**
 * @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 }