首页 > 技术文章 > sequelize如何做到左外连接

antyhouse 2020-07-06 15:07 原文

参考: https://www.cnblogs.com/wuweixin/p/9402125.html

前提: 前端开发负责写前端页面以及node开发,node是基于egg.js,node的orm用的是sequelize

例如一个游戏记录表需要一个关联一个HxGameGames的表

/**
   * 游戏记录列表
   * @param {Object} body 传入参数
   * @param {Object} body.params ...params是除去limit,offset之后剩余的参数
   */
  async gameRecord({ limit, offset, ...params }) {
    const { rows, count } = await this.ctx.model.HxGameSummaryUserGame.findAndCountAll({
      attributes: { exclude: [ 'createdAt', 'updatedAt' ] },
      where: {
        ...params,
      },
      include: [
        {
          model: this.app.model.HxGameGames,
          as: 'game',
        },
      ],
      offset,
      limit,
    })
    return { list: rows, total: count }
  }

那么这里include默认的就是内连接

内连接:两个表都满足条件的情况下,返回公有数据
左外连接: 左表所有数据,右表匹配不到的数据为null
右外连接:保证右表所有数据,左表匹配不到的数据null填充

假如前端需要实现一个页面,就是table,里面有很多的字段,在node端的处理就是user主表要关联baseInfo表,并且在做数据筛选的时候有对baseInfo表的userName进行筛选.不管baseInfo表的数据存在不存在,我需要体现完整的user主表的条数,并且筛选不出问题,那么我们需要做的就是将include变成左外连接,这里用required:false来实现
官方文档: https://sequelize.org/master/manual/eager-loading.html#referring-to-other-columns

 /** 用户列表导出
   * @param { Object } body 查询条件数据对象
   * @param { String } body.userName 用户名
   * @param { Object } body.time 时间
   * @return { Object } list用户列表集合 total当前筛选条件下的记录总条数
   */
  async exportUserList({ userName = '', time, ...params }) {
    const { Op } = this.app.Sequelize
    const { rows, count } = await this.ctx.model.HxUser.findAndCountAll({
      attributes: { exclude: [ 'createdAt', 'updatedAt' ] },
      distinct: true,
      where: {
        ...time,
        ...params,
      },
      // 如果没有设置required: false的话 是inner 连接,如果设置了就是左连接
      include: [{
        model: this.app.model.HxUserBaseInfo,
        as: 'basic',
        required: !!userName,
        where: {
          userName: {
            [Op.like]: `%${userName}%`,
          },
        },
      },
      ],
    })
    return { list: rows, total: count }
  }

如果我直接去设置false的话, 那会变成左连接,意思就是假如user表有10数据,不管你怎么筛选,筛选出来的数据永远都是10条, required: !!userName 表示的就是 userName不存在时就是空,那么就是required: false, 左外连接出现全部的,如果存在的时候,直接内连接,直接筛选userName的数据为准

如果大家有更好的建议,欢迎提出来

推荐阅读