sequelize使用总结(egg.js)

2,423 阅读4分钟

sequelize中文文档
sequelize英文文档
egg中文文档

想到哪个知识点就总结一下,包含sequelize框架以及egg.js相关知识,主要还是看文档中的例子~中文文档没有那么完善,大部分的知识点还是要在英文文档上找。

1 修改返回的数据

toJSON()

const { list, total } = await this.service.activityManage.xxxx.xxxx()
const transferList = list.map(node => {
  const item = node.toJSON()
  const { powerRecordObj, ...rest } = item
  return { ...powerRecordObj, ...rest }
})

find查到的数据,是Model对象,可以用toJSON()转成JSON

2 模型查询基础

Model Basics - 模型基础

2.1 Op.between

筛选出被包含在startTime, endTime之间的数据,如果createdAt等于startTime/endTime也会被筛选出

const { Op } = this.app.Sequelize
where: {
    createdAt: {
      [Op.between]: [ startTime, endTime ],
    },
}
2.2 模糊搜索Op.like
where: {
     sqlText: { [Op.like]: `%${sqlText}%` },
 }
2.3 Op.in

查询包含这些ids的数据

 where: {
    id: { [Op.in]: ids },
  },
2.4 and or连用

返回bannerId为传入的id,并且返回uv,click,comment至少一个不为0的数据,像这种情况可以使用and or连用

 where: {
    [Op.and]: [
      { bannerId: id },
    ],
    [Op.or]: [
      { uv: { [Op.ne]: 0 } },
      { click: { [Op.ne]: 0 } },
      { comment: { [Op.ne]: 0 } },
    ],
  },
2.5 与fn连用

表示返回relatedCpGame.game_id不为null的数据

where : {
  XXXX,
  [Op.and]: [{
    [Op.not]: fn('ISNULL', col('relatedCpGame.game_id')),
  }],
}
2.6 not and连用

返回startHomeTimes,startHomeUser,beginUserNum不全为0的数据

   {
      [Op.not]: {
        [Op.and]: [
          { startHomeTimes: { [Op.eq]: 0 } },
          { startHomeUser: { [Op.eq]: 0 } },
          { beginUserNum: { [Op.eq]: 0 } },
        ],
      },
    }

3 literal的使用

literal
sequelize.literal() 方法用于创建一个字面量对象,该对象(val)会被直接传入所生成的 SQL 语句中,而不会进行任何转义

const { Op, literal } = app.Sequelize
const [ summaryData ] = await ctx.xxxx.xxxxx.findAll({
  attributes: [
    [ literal('COUNT(id)'), 'count' ],
    [ literal('IFNULL(SUM(pv), 0)'), 'pv' ],
  ],
  raw: true,
})
 whereObj = {
    startTime: {
      [Op.gte]: literal(`FROM_UNIXTIME(${start})`),
    },
    endTime: {
      [Op.lte]: literal(`FROM_UNIXTIME(${end})`),
    },
  }

4 关联

Associations - 关联

1.BelongsTo
2. HasOne
3. HasMany
4. BelongsToMany

假设user为用户表,里面有用户id,字段名称为id
userInfo为用户信息表,用户id的字段名称为userId,并且里面有a表需要的phone字段 userGameRecord为购买记录表,用户id的字段名称为userId,一个用户有多个购买记录,user表需要获取所有的购买记录总数

4.1 user主表关联userInfo表,获取用户信息

user.associate = function() {
    this.hasOne(app.model.userInfo, { foreignKey: 'userId', sourceKey: 'id', as: 'userInfo' })
}
 userInfo.associate = function() {
    this.belongsTo(app.model.user, { foreignKey: 'userId', targetKey: 'id', as: 'jointUser' })
  }
 include: [
    {
      model: this.app.model.userInfo,
      as: 'userInfo',
    },
  ],

4.2 user主表关联userGameRecord表,获取用户游戏记录

user.associate = function() {
    this.hasMany(app.model.userGameRecord, { foreignKey: 'userId', sourceKey: 'id', as: 'gameInfo' })
}
 userGameRecord.associate = function() {
    this.belongsTo(app.model.user, { foreignKey: 'userId', targetKey: 'id', as: 'gameInfo' })
  }
 include: [
    {
      model: this.app.model.userGameRecord,
      as: 'gameInfo',
    },
  ],

5 如何连接2个数据库,并且写sql

egg-sequelize 原始查询

在config/config.default写入

// 各种环境配置
const dataBaseLogMap = {
  local: {
    database: 'xxxxx',
  },
}

module.exports = () => {
  return {
    // 数据库配置
    sequelize: {
      datasources: [{
        delegate: 'model',
        baseDir: '../../xxxx/model',
        ...dataBaseMap[nowMode],
      }, {
        delegate: 'testLog',
        baseDir: '../../xxxx/test_log',
        ...dataBaseLogMap[nowMode],
      }],
    },
  }
}

写sql

  const [{ total }] = await this.ctx.model.query(
      `select xxxxxxxxxxxxxxxxx`,
      { type: 'SELECT', replacements }
    )

6 curl

curl

有时候也许服务端会给我们提供接口,所以我们为了保持统一性,我们需要在node端中转一下,下面实现如何直接调用服务端接口

ctx = new Context()

1633749677.png

const { ctx } = this
const result = await ctx.curl('http://example.com/foo.json', 
{ method: 'GET', dataType: 'json', }); 
console.log(result.status, result.headers, result.data);

7 如何调用通用的方法

Application

1633752248(1).png 在egg.js项目里面,app 同级目录建立一个utils文件

1633750838(1).png

如果存在一个方法

'use strict'
module.exports = {
  /**
   * 生成随机名字
   * @param { number } randomNum 随机码个数
   * @return { string } 随机名字
   */
  getRandomName(randomNum = 4) {
     xxxxxx
  },
}

在service和controller都可以调用

  const { app } = this
  const res = app.utils.index.getRandomName()

8 如何进行参数校验

egg.js插件入口 egg-validate

1.先在config/plugin.js中配置

  validate: {
    enable: true,
    package: 'egg-validate',
  },

2.在controller中使用

    ctx.validate({
      min_reward_wealth: { required: true, type: 'string' },
      max_reward_wealth: { required: true, type: 'number' },
    })

9 成功返回数据的函数

ctx.body, ctx.status

主要返回状态和数据

  success({ status = 200, code = 0, msg = 'success', data } = {}) {
    this.ctx.body = {
      code,
      msg,
      data,
    }
    this.ctx.status = status
  }
const list = await service.activityManage.xxxx.xxxx()
this.success({ data: { list } })

10 如何设置请求信息

ctx.set

ctx.set('Content-type', 'application/octet-stream')

11 排序

order

11.1对id进行倒叙,这是对主表进行排序,如果有子表,可以加上表名。
 const { rows, count } = await this.ctx.model.xxxx.findAndCountAll({
  order: [[ 'id', 'DESC' ]],
})
11.2对主表和子表进行排序
async xxxxx() {
    const { rows, count } = await this.ctx.model.xxxxx.findAndCountAll({
      include: [
        {
          model: this.app.model.xxxxx,
          as: 'rewardVipGames',
        },
      ],
      order: [[ 'startDate', 'ASC' ], [ 'rewardVipGames', 'sort', 'ASC' ]],
    })
    return { list: rows, total: count }
  }

12 查找器

model apis

Model相当于数据库中表,有时它也会被称为“模型”或“工厂”。
Model不能通过构造函数创建,
而只能通过sequlize.define方法来定义或通过sequlize.import导入。通过define定义一个Model,就相当于定义了
一种模型与数据表之间的映射关系,通过模型可以实现对表记录的增、删、改、查等操作

Finders - 模型查询(查找器)

findAll 不需要分页,查找所有的数据
findOne 查到第一条
findAndCountAll 需要条数进行分页的

12.1 bulkCreate 批量插入
   const gameArr = gameData.map((item, sort) => {
      return {
        gameId: item.gameId,
        tagId: id,
        sort, // 排序
      }
    })
    return await this.ctx.model.XXXXX.bulkCreate(gameArr, { transaction }) // 批量插入
12.2 destory
return this.ctx.model.xxxxx.destroy({
  where: {
    id,
  },
})

13 separate: true

separate: true stackoverflow.com/questions/3…

  const { rows: list, count: total } = await ctx.model.test1.findAndCountAll({
      attributes: { exclude: [ 'createdAt', 'updatedAt' ] },
      include: [
        {
          model: app.model.test2,
          attributes: [ 'id' ],
          as: 'missionSaving',
          separate: true,
        },
      ],
      order: [[ 'enable', 'DESC' ], [ 'createdAt', 'DESC' ]],
      limit,
      offset,
    })

'createdAt', 'DESC'是对子表的排序,这时候应该加上separate: true,主表test1与test2是一对多的关系

如何写一个接口,以及前端调用,可以参考我这篇: 用egg.js实现路由以及前端接口调用

最近在写一个公众号[程序媛爱唠嗑],主要是分享前端以及生活中一些小事,有兴趣的关注哈,没有代码,只有故事~

生活愉快-_-