相关文章推荐
可爱的可乐  ·  WPF ...·  1 年前    · 
好帅的草稿本  ·  Python ...·  2 年前    · 

如何用sequelize提供的方法,实现多对多联表查询?

我们以 RBAC (Role-Based Access Control,基于角色的访问控制)来举例说明。
简单地说,一个用户拥有若干角色,每一个角色拥有若干权限。这样,就构造成“用户-角色-权限”的授权模型。(如下图)

这里我们先以 用户表和角色表的关联查询 为例子,我们引入了一个用户角色关联表,来绑定用户id和角色id之间的对应关系。

模型的定义

数据库中的表之间存在一定的关联关系,表之间的关系基于主/外键进行关联、创建约束等。 关系表中的数据分为1对1(1:1)、1对多(1:M)、多对多(N:M)三种关联关系。

在Sequelize中建立关联关系,通过调用模型(源模型)的 belongsTo、hasOne、hasMany、belongsToMany 方法,再将要建立关系的模型(目标模型)做为参数传入即可。

model建好后,需要在model导出前,通过model.associate方法来指定表和表之间的关联关系。而在有中间表的情况下,可以直接在中间表里指定了关系,另外两张表就不需要去重复指定了。具体代码如下:

用户表模型:app.model.Users

'use strict';
const moment = require('moment');
module.exports = app => {
  const { STRING, INTEGER, DATE} = app.Sequelize;
  const User = app.model.define('users', {
    id: { type: INTEGER, primaryKey: true, autoIncrement: true }, // 主键,自增
    username: { type: STRING(30), allowNull: false, unique: true }, // 不允许为空,必须唯一
    mobile: { type: STRING}, // 手机号
    created_at: {	
      type: DATE,
      get() {
      	//获取时间时格式化
        return moment(this.getDataValue('created_at')).format('YYYY-MM-DD HH:mm:ss');
    updated_at: {
      type: DATE,
      get() {
        return moment(this.getDataValue('created_at')).format('YYYY-MM-DD HH:mm:ss');
  }, {
    freezeTableName: true, // 防止修改表名为复数
  });
  return User;

角色表模型:app.model.Role

'use strict';
module.exports = app => {
  const { STRING, INTEGER } = app.Sequelize;
  const Role = app.model.define('role', {
    id: { type: INTEGER, primaryKey: true, autoIncrement: true }, // 主键,自增
    name: { type: STRING(30), unique: true },
    describe: STRING(60),
  }, {
    freezeTableName: true,
  });
  return Role;

用户角色关联表模型:app.model.UsersRole

'use strict';
module.exports = app => {
  const { INTEGER, DATE } = app.Sequelize;
  const UsersRole = app.model.define('users_role', {
    id: { type: INTEGER, primaryKey: true, autoIncrement: true }, // 主键,自增
    users_id: { type: INTEGER },
    role_id: { type: INTEGER },
    created_at: DATE,
    updated_at: DATE,
  }, {
    freezeTableName: true, 
  });
  UsersRole.associate = function() {
    // 用belongsToMany指定多对多关联关系,并指定外键
    app.model.User.belongsToMany(app.model.Role, {
      through: UsersRole,
      foreignKey: 'users_id',
      otherKey: 'role_id',
    });
    app.model.Role.belongsToMany(app.model.User, {
      through: UsersRole,
      foreignKey: 'role_id',
      otherKey: 'users_id',
    });
  return UsersRole;

在controller.Users里实现联表查询

在findAll方法里,通过include参数引入需要关联的表,这时候这两个表的外键早已在创建用户角色模型时指定好了,直接引入角色模型就可以实现联表查询。

async getUserList() {
    const { ctx } = this;
    const id = toInt(ctx.request.body.userId);
    const users = await ctx.model.User.findAll({
      include: [
        { model: ctx.model.Role },
      where: {
    });
    if (!user) {
      ctx.status = 404;
      return;
    ctx.body = {result:users}

查询出来的结果,会在users列表里的每个user里,会多出一个roles的角色列表

"result": [
			"created_at": "2022-02-23 13:27:50",
			"updated_at": "2022-02-23 13:27:50",
			"id": 999,
			"username": "Tony",
			"roles": [
					"id": 1,
					"name": "超级管理",
					"describe": "eee23456",
					"createdAt": "2022-02-23T02:59:21.000Z",
					"updatedAt": "2022-02-24T06:41:33.000Z",
					"users_role": {
						"id": 1,
						"users_id": 999,
						"role_id": 1,
						"createdAt": "2022-02-24T08:13:38.000Z",
						"updatedAt": "2022-02-24T08:13:42.000Z"
 

这里我们只讨论了复杂点的多对多情况,其他联表方法可以参考官网文档:【点击跳转到sequlize文档】

关联查询包含一对多和多对一的映射关系,一对多的API为belongsTo,多对一的API为hasMany。使用sequelize进行关联查询时,要根据具体情况选择用哪一个映射关系,因为这其中涉及左右连接、内外连接的性能问题。下面来看一个一对多的例子,当然你可以将这个例子反过来多对一,但是性能会差很多。所以我们要根据数据库的设计来选择谁关联谁 假设有一个Student包含id、name、age、address、gender、c_id这几个属性,还有一个Class包含id、c...
之前的文章说了sequelize对于事物的处理,包括说自动提交的事务以及手动提交回滚的事物。而对于java来说事务相对来说用起来简单一些,个人是这样认为的。 这次来说一下关联查询与批量查询: 都知道,关联关系主要有三种:一对一,一对多,多对多,我记得javayou一个批量的方法就是addbatch进行批量的操作,言归正传sequelize对于一对一的处理你可以用find相关的方法比如说:fin...
//关键语句 sequelizeSequelize.where(Sequelize.col(`table.name`), { [Op.like]: `%${value}%` }) mysql:where table.name LIKE %value% sequelizeSequelize.where(Sequelize.col(`table.name`),value) mysql:where table.name=value mysql: SELECT 在sequelize中,之间用代码来说存在三种关联关系:一对一,一对多,多对多 hasOne()和belongsTo()第一个参数为本关联的另外一个的Model实例,第二个参数中,都有foreginKey属性,对hasOne来说,这个属性值是对方与自己Id对应的字段,对belongsTo来说,这个属性值是本上的与对方id对应的字段名。belongsTo比hasOne多了个targetKey属性,其为对方的对应主键名 一对一的方 二、需求: 查询Match中的user_id,report_comment,以及job_history_id所关联的JOB中的job_link,在前端显示。 三、Code: 1. 后端 首先要建立两个的关联: MatchScoreReportModel.belongsTo(JobHistoryModel, { foreignKey: 'job_history
nodejs的orm模块sequelize功能很强大也很深奥,记录下今天使用hooks 及 association遇到了几个坑。 hooks:顾名思义就是钩子,简单的理解为可以定义相关动作后的关联动作 association: 关联,显式的指定该模型关联关系。个人觉得 ORM 最大的问题就是关联查询及其复杂,反人类简直。有了 association 就可以显式的指定关联,方便查询。 定义modle 在定义modle的时候还比较容易,只需要在正常的定义后面加上 hooks 和 association 部
之间的关联关系有三种:一对一,一对多,多对多。要进行多操作,首先要建立之间的关联关系,在sequelize中分别使用hasOne,hasMany和belongsToMany示以上三中关系。例如我们要建立user与role多对多的关联,可以这样写,首先要建立外键(当然也可以在两张之间建立中间) 本文主要完成多操作简单的部分,熟悉在多建立关联关系并且可以完成简单的联操作,以联表查询为例。 登录成功时返回结果中要包含角色信息,以便展示对应的权限菜单 查询用户时返回...
var SysUser = sequelize.import('../models/SysUser.js'); var MonitorSetting = sequelize.import('../models/MonitorSetting.js'); var Car = sequelize.import('../models/Car.js'); var Camera = sequelize.imp...
const { Sequelize, DataTypes } = require('sequelize'); const sequelize = new Sequelize({ host: '127.0.0.1', port: 3306, username: 'root', const seq = new Sequelize('数据库名称', '数据库用户名', '密码', { host: 'localhost',//主机地址 dialect: "mysql", // 测试数据库连接 // seq // .