【问题标题】:Sequelize: Instance Methods and Properties returned from Query are undefinedSequelize:从 Query 返回的实例方法和属性未定义
【发布时间】:2021-09-04 21:13:42
【问题描述】:

续集:@​​987654321@

Mysql2:2.2.5

我已经像这样定义了我的Model 并设置了这样的方法:

interface IUserAttributes {
  user_id: number;
  logon_name: string;
  user_password: string;
  full_name: string;
  disable_user: number;
  district_code: number;
  created_modified: Date;
}

interface IUserCreationAttributes extends Optional<IUserAttributes, 'user_id'> { }

export class User
  extends Model<IUserAttributes, IUserCreationAttributes>
  implements IUserAttributes {
  public user_id!: number;
  public logon_name!: string;
  public user_password!: string;
  public full_name!: string;
  public disable_user!: number;
  public district_code!: number;
  public created_modified!: Date;

  public readonly user_assigned_level: UserAssignedLevel;

  public static associations: {
    user_assigned_level: Association<User, UserAssignedLevel>
  }

  public toUserJSON: () => User;
  public generateAccessToken: (payload: IUser) => string;
  public generateRefreshToken: (payload: IUser) => string;
  public getRole: () => 'meter_reader' | 'evaluator' | null;

}

User.prototype.toUserJSON = function () {
  const keysToDelete = ['user_password'];
  const obj = this.toJSON();

  keysToDelete.forEach((key) => delete obj[key]);

  return obj;
}

User.prototype.getRole = function (): 'meter_reader' | 'evaluator' {
  const userLevel = this.user_assigned_level.user_level_id;
  let role = null;

  if (userLevel === 13) {
    role = 'meter_reader';
  } else if (userLevel === 9) {
    role = 'evaluator';
  }

  return role;
}

User.init(
  {
    user_id: {
      autoIncrement: true,
      type: DataTypes.SMALLINT,
      allowNull: false,
      primaryKey: true
    },
    logon_name: {
      type: DataTypes.STRING(20),
      allowNull: false
    },
    user_password: {
      type: DataTypes.STRING(20),
      allowNull: false
    },
    full_name: {
      type: DataTypes.STRING(100),
      allowNull: false
    },
    disable_user: {
      type: DataTypes.TINYINT.UNSIGNED,
      allowNull: false,
      defaultValue: 0
    },
    district_code: {
      type: DataTypes.CHAR(2),
      allowNull: true
    },
    created_modified: {
      type: DataTypes.DATE,
      allowNull: false,
      defaultValue: literal('CURRENT_TIMESTAMP')
    }
  },
  {
    sequelize: DBInstance,
    tableName: 'users',
    timestamps: false,
    underscored: true,
    defaultScope: {
      attributes: {
        exclude: ['user_password']
      }
    },
    scopes: {
      withoutPassword: {
        attributes: { exclude: ['user_password'] },
      }
    },
  }
);

// foreignKey of Model to target
User.hasOne(UserAssignedLevel, {
  foreignKey: 'user_id',
  as: 'user_assigned_level' // this determines the name in `associations`
});

当我查询一个用户并尝试使用我定义的toUserJSON() 方法时,它失败了

const user = await User.findOne({
  include: {
     model: UserAssignedLevel,
     as: 'user_assigned_level',
     where: {
        [Op.or]: [
          { user_level_id: 9 },
          { user_level_id: 13 },
        ]
      },
    },
    where: {
      logon_name: username,
      disable_user: 0
    },
    attributes: {
       include: ['user_id', 'logon_name', 'user_password', 'disable_user'],
       // exclude: ['user_password']
    },
   });

   if (!user) {
     return next(new ErrorHandler(401, 'Incorrect credentials.'));
   }


   const result = user.toUserJSON(); // user.toUserJSON is not a function

当我在控制台中记录user 实例的值时,它会像这样返回。 当我尝试访问像user_idlogon_name 这样的属性值时,它总是返回未定义。我必须像user.getDataValue('user_id') 一样使用getDataValue() 才能访问该字段。

User {
  dataValues: {
    user_id: 581,
    logon_name: 'cha',
    full_name: 'CHARISSE SUNGA',
    disable_user: 0,
    district_code: '9',
    created_modified: 2021-03-24T01:52:14.000Z,
    user_password: 'èÀ‘\x81k\x8D²pœUìOÌ:\x9D´',
    user_assigned_level: UserAssignedLevel {
      dataValues: [Object],
      _previousDataValues: [Object],
      _changed: Set(0) {},
      _options: [Object],
      isNewRecord: false,
      user_assigned_level_id: undefined,
      user_id: undefined,
      user_level_id: undefined,
      created_modified: undefined
    }
  },
  _previousDataValues: {
    user_id: 581,
    logon_name: 'cha',
    full_name: 'CHARISSE SUNGA',
    disable_user: 0,
    district_code: '9',
    created_modified: 2021-03-24T01:52:14.000Z,
    user_password: 'èÀ‘\x81k\x8D²pœUìOÌ:\x9D´',
    user_assigned_level: UserAssignedLevel {
      dataValues: [Object],
      _previousDataValues: [Object],
      _changed: Set(0) {},
      _options: [Object],
      isNewRecord: false,
      user_assigned_level_id: undefined,
      user_id: undefined,
      user_level_id: undefined,
      created_modified: undefined
    }
  },
  _changed: Set(0) {},
  _options: {
    isNewRecord: false,
    _schema: null,
    _schemaDelimiter: '',
    include: [ [Object] ],
    includeNames: [ 'user_assigned_level' ],
    includeMap: { user_assigned_level: [Object] },
    includeValidated: true,
    attributes: [
      'user_id',
      'logon_name',
      'full_name',
      'disable_user',
      'district_code',
      'created_modified',
      'user_id',
      'logon_name',
      'user_password',
      'disable_user'
    ],
    raw: true
  },
  isNewRecord: false,
  user_assigned_level: undefined,
  user_id: undefined,
  logon_name: undefined,
  user_password: undefined,
  full_name: undefined,
  disable_user: undefined,
  district_code: undefined,
  created_modified: undefined,
  toUserJSON: undefined,
  generateAccessToken: undefined,
  generateRefreshToken: undefined,
  getRole: undefined
}

如您所见,dataValues 之外的方法和属性都是未定义的。

【问题讨论】:

    标签: node.js typescript sequelize.js


    【解决方案1】:

    对于遇到同样问题的任何人,我设法通过在类定义中设置方法来解决问题。

    但是,像this.username 这样直接访问属性仍将返回未定义。您可以使用getDataValue 方法this.getDataValue('username')get 方法const user = this.get({ plain:true }) 访问属性

    export class UserAuth
      extends Model<IUserAuthAttributes, IUserAuthCreationAttributes>
      implements IUserAuthAttributes {
    
      public user_auth_id!: number;
      public username!: string;
      public password!: string;
      public full_name!: string;
      public disable_user: number;
      public user_level_id!: number;
      public created_modified: string | Date;
    
      // Set the method here
       getRole() {
        const user = this.get({ plain: true });
    
        let role = null;
    
        if (user.user_level_id === 13) {
          role = 'meter_reader';
        } else if (user.user_level_id === 9) {
          role = 'evaluator';
        }
    
        return role;
      }
    }
    

    【讨论】:

    • 但是这个解决方案只是对使用打字稿的原因很生气:类型检查。你找到解决这个问题的真正方法了吗?
    • @pihentagy 我实际上在 sequelize repo here 上打开了这个问题,问题的原因似乎是我的 tsconfig.json 配置。我只是将target 属性更改为ESNEXT,它解决了我的问题。
    • 对我来说,解决方案是相反的。将 ESNext 更改为其他任何东西都可以解决问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-17
    • 2017-08-28
    • 2018-09-05
    • 2022-08-20
    • 2019-04-04
    • 2019-08-30
    • 2016-01-10
    相关资源
    最近更新 更多