NodeJS - Sequelize 如何仅声明一次预加载关联,以便稍后用于查询

NodeJS - Sequelize how to declare association for eager loading only once to be used for queries later

问题:

每当我获取用户时,我总是必须 declare/include 查询中的关联才能获得其角色:

const user = await DB.PORTALDB.models.AccessUser.findOne({
   where: { email },
   include: [ // EVERY QUERY, I HAVE TO INCLUDE THIS
      {
       model: DB.PORTALDB.models.AccessUserRoleLup,
       as: 'role'
      }
   ]
});

现在有些情况下我忘记包含此关联,所以我得到了一个 undefined 角色。

我的问题是,有没有一种方法可以让我只设置一次这个关联,这样我以后就不必在我的查询中包含它了?

这是我的模型 AccessUser table

const AccessUser = <AccessUserStatic>sequelize.define<AccessUserInstance>(
    'AccessUser',
    {
      user_id: {
        autoIncrement: true,
        type: DataTypes.INTEGER.UNSIGNED,
        allowNull: false,
        primaryKey: true
      },
      email: {
        type: DataTypes.STRING(255),
        allowNull: false
      },
      firstname: {
        type: DataTypes.STRING(255),
        allowNull: false
      },
      lastname: {
        type: DataTypes.STRING(255),
        allowNull: false
      },
      password: {
        type: DataTypes.STRING(255),
        allowNull: false
      },
      disable: {
        type: DataTypes.TINYINT,
        allowNull: false,
        defaultValue: 0
      },
      role_id: {
        type: DataTypes.SMALLINT,
        allowNull: false,
        defaultValue: 0
      },
      created_modified: {
        type: DataTypes.DATE,
        allowNull: false,
        defaultValue: Sequelize.literal('CURRENT_TIMESTAMP')
      }
    }, {
    tableName: 'access_user',
    timestamps: false,
    indexes: [
      {
        name: "PRIMARY",
        unique: true,
        using: "BTREE",
        fields: [
          { name: "user_id" },
        ]
      },
    ]
  });

AccessUserRoleLup table

const AccessUserRoleLup = <AccessUserRoleLupStatic>sequelize.define<AccessUserRoleLupInstance>(
    'AccessUserRoleLup',
    {
      role_id: {
        autoIncrement: true,
        type: DataTypes.INTEGER.UNSIGNED,
        allowNull: false,
        primaryKey: true
      },
      role_name: {
        type: DataTypes.STRING(50),
        allowNull: false
      },
      role_code: {
        type: DataTypes.CHAR(50),
        allowNull: false,
        defaultValue: ""
      }
    }, {
    tableName: 'access_user_role_lup',
    timestamps: false,
    indexes: [
      {
        name: "PRIMARY",
        unique: true,
        using: "BTREE",
        fields: [
          { name: "role_id" },
        ]
      },
    ]
  });

协会:

db.models.AccessUser.hasOne(db.models.AccessUserRoleLup, {
  foreignKey: 'role_id',
  as: 'role'
});

我最初的解决方法是创建一个实用函数来查询用户,如下所示:

export const getAccessUser = (where: WhereOptions, include?: IncludeOptions) => {
    return new Promise(async (resolve, reject) => {
        try {
            const user = await DB.PORTALDB.models.AccessUser.findOne({
                where: where,
                include: [
                    {
                        model: DB.PORTALDB.models.AccessUserRoleLup,
                        as: 'role'
                    },
                    ...[include]
                ]
            });

            resolve(user);
        } catch (err) {
            reject(err);
        }
    });
}

我想知道我上面的问题是否可以用更简单的方式来解决。

AccessUser 使用 defaultScopedefaultScope 在模型定义中定义并始终应用(除非您删除内联)。

const AccessUser = <AccessUserStatic>sequelize.define<AccessUserInstance>(
'AccessUser', 
{
  user_id: {
    autoIncrement: true,
    type: DataTypes.INTEGER.UNSIGNED,
    allowNull: false,
    primaryKey: true
  },
  ...
}, {
  tableName: 'access_user',
  timestamps: false,
  defaultScope: {     // Add this 
    include: [{
      model: AccessUserRoleLup,
      as: 'role'
    }]
  },
  ...
});

使用此模型定义,所有查询都将包含 AccessUserRoleLup

如果您想删除某个查询,请使用 .unscoped()

// These will automatically add eager loading for role
DB.PORTALDB.models.AccessUser.findAll()
DB.PORTALDB.models.AccessUser.findOne() 

// These won't fetch role
DB.PORTALDB.models.AccessUser.unscoped().findAll()
DB.PORTALDB.models.AccessUser.unscoped().findOne()

有关范围的更多详细信息:https://sequelize.org/master/manual/scopes.html