【问题标题】:Sequelize join table not retuning additional fieldSequelize 连接表不重新调整附加字段
【发布时间】:2020-03-27 23:24:51
【问题描述】:

我正在测试 Sequelize,到目前为止我很喜欢它。现在我遇到了一个我无法解决的问题,也没有从网上找到任何答案。

所以我有这三个通过迁移创建的表

用户:

'use strict';
module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.createTable('Users', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      .
      . // All user data here
      .
    });
  },
  down: (queryInterface, Sequelize) => {
    return queryInterface.dropTable('Users');
  }
};

属性:

'use strict';
module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.createTable('Properties', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      .
      . // All property data here
      .
    });
  },
  down: (queryInterface, Sequelize) => {
    return queryInterface.dropTable('Properties');
  }
};

和 PropertyUser:

'use strict';
module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.createTable('PropertyUsers', {
      property_id: {
        type: Sequelize.INTEGER,
        allowNull: false,
        primaryKey: true,
        references: {
          model: 'Properties',
          key: 'id'
        }
      },
      user_id: {
        type: Sequelize.INTEGER,
        allowNull: false,
        primaryKey: true,
        references: {
          model: 'Users',
          key: 'id'
        }
      },
      role: {
        type: Sequelize.ENUM('admin', 'basic', 'read'),
        allowNull: false,
        defaultValue: 'read'
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE
      }
    });
  },
  down: (queryInterface, Sequelize) => {
    return queryInterface.dropTable('PropertyUsers');
  }
};

所以我们有通过 PropertyUser 表连接的用户和属性表,而 PropertyUser 表保存有关用户在属性中的角色(管理员、基本、读取)的信息。

我也创建了这些模型

用户:

'use strict';
module.exports = (sequelize, DataTypes) => {
  const User = sequelize.define('User', {
    firstname: DataTypes.STRING,
    .
    .
    .
  }, {});
  User.associate = function(models) {
    // associations can be defined here
    User.belongsToMany(models.Property, {through: 'PropertyUsers', foreignKey: 'user_id', as: 'properties'})
  };
  return User;
};

属性:

'use strict';
module.exports = (sequelize, DataTypes) => {
  const Property = sequelize.define('Property', {
    .
    .
    .
  }, {});
  Property.associate = function(models) {
    // associations can be defined here
    Property.belongsToMany(models.User, {through: 'PropertyUsers', foreignKey: 'property_id', as: 'users'})
  };
  return Property;
};

物业用户:

'use strict';
module.exports = (sequelize, DataTypes) => {
  const PropertyUser = sequelize.define('PropertyUser', {
    property_id: DataTypes.INTEGER,
    user_id: DataTypes.INTEGER,
    role: DataTypes.ENUM('admin', 'basic', 'read'),
  }, {});
  PropertyUser.associate = function(models) {
    // associations can be defined here
    PropertyUser.belongsTo(models.Property, {foreignKey: 'property_id'});
    PropertyUser.belongsTo(models.User, {foreignKey: 'user_id'});
  };
  PropertyUser.removeAttribute('id');
  return PropertyUser;
};

现在,当我尝试使用 ID 获取属性并包含属于该属性的用户时,它会返回每个用户的联接表数据,但联接表数据仅包括 user_id、property_id、createdAt 和 updatedAt 而不是角色。

这是我用来获取数据的代码。

return new Promise(async(resolve, reject) => {
        try {
            const result = await models.Property.findOne({
                where: {
                    id: propertyId
                },
                include: [{
                    model: models.User,
                    as: 'users',
                }]
            });
            resolve(result);
        } catch (e) {
            reject(e);
        }
    });

我做错了什么?已经感谢您的帮助!

编辑: 似乎当 Sequelize 构造 SQL 语句时,它并没有将角色添加到语句中。这是从 PropertyUser 表中获取数据的语句部分

`users->PropertyUsers`.`createdAt` AS `users.PropertyUsers.createdAt`, `users->PropertyUsers`.`updatedAt` AS `users.PropertyUsers.updatedAt`, `users->PropertyUsers`.`property_id` AS `users.PropertyUsers.property_id`, `users->PropertyUsers`.`user_id` AS `users.PropertyUsers.user_id`

【问题讨论】:

    标签: mysql node.js sequelize.js


    【解决方案1】:

    模型 PropertyUser 将包含在 User 模型中。

    这意味着您将获得类型为Array<User & {PropertyUser: PropertyUser}>;的用户

    您可以通过result.users[0].PropertyUser.role访问PropertyUser

    这是我在打字稿中的实现。我正在使用带有 sequelize 的 sequelize-typescript。

    客户表

    @Table({
      timestamps: true,
      paranoid  : true,
      tableName : "clients"
    })
    export class Client extends Model<Client> {
    
      @Unique
      @PrimaryKey
      @AutoIncrement
      @Column(DataType.BIGINT)
      id: number;
    
      @Column(DataType.STRING)
      name: string;
    
      @BelongsToMany(() => User, () => ClientUser)
      users?: Array<User & {ClientUser: ClientUser}>;
    }
    

    用户表

    @Table({
      timestamps: true,
      paranoid  : true,
      tableName : "users"
    })
    export class User extends Model<User> {
      @Unique
      @PrimaryKey
      @AutoIncrement
      @Column(DataType.BIGINT)
      id: number;
    
      @Column(DataType.STRING)
      first_name: string;
    
      @Column(DataType.STRING)
      last_name?: string;
    
    
      @BelongsToMany(() => Client, () => ClientUser)
      clients?: Array<Client & { ClientUser: ClientUser }>;
    }
    

    客户用户表

    @Table({
      timestamps: true,
      paranoid: false,
      tableName: "client_user"
    })
    export class ClientUser extends Model<ClientUser> {
    
      @Unique
      @PrimaryKey
      @AutoIncrement
      @Column(DataType.BIGINT)
      id: number;
    
      @ForeignKey(() => Client)
      @Column(DataType.BIGINT)
      client_id: number;
    
      @ForeignKey(() => User)
      @Column(DataType.BIGINT)
      user_id: number;
    
      @Column(DataType.STRING)
      role: string;
    
      @BelongsTo(() => Client)
      client: Client;
    
      @BelongsTo(() => User)
      user: User;
    }
    

    查询

    const clients = await Client.findAll({
          include: [
            {
              model: User,
              as   : "users"
            }
          ],
        });
    
        console.log("clients", clients.map(c => {
          return {
            id   : c.id,
            name : c.name,
            users: c.users.map(u => {
              return {
                id        : u.id,
                first_name: u.first_name,
                role      : u.ClientUser.role
              };
            })
          };
        }));
    

    结果

    【讨论】:

    • 是的,PropertyUser 包含在 result.users[0] 中,但它没有角色字段。它只有 user_id、property_id、createdAt 和 updatedAt。这就是结果不包括角色的问题,我不知道为什么。
    • 你用的是哪个版本的sequelize?
    • 在我的 package.json 我有 sequelize: ^5.21.2sequelize-cli: ^5.5.1
    • 我检查了我的系统,它按预期工作。我的续集版本是:4.44.3
    • 这太奇怪了。我已经测试将版本更改为 4.44.3,但仍然没有成功。不知道为什么它不想返回角色。
    【解决方案2】:

    经过几个小时的尝试不同的事情,我能够找到问题所在。我不知道为什么它不适用于我在原始帖子中的实现方式,但这里有一些变化。

    在用户模型中我改变了

    User.belongsToMany(models.Property, {through: 'PropertyUsers', foreignKey: 'user_id', as: 'properties'})
    

    to(注意通过的变化)

    User.belongsToMany(models.Property, {through: models.PropertyUser, foreignKey: 'user_id', as: 'properties'})
    

    在属性模型中也一样,我将 through: 'PropertyUsers' 更改为 through: models.PropertyUser

    【讨论】:

      猜你喜欢
      • 2018-08-18
      • 2017-07-31
      • 1970-01-01
      • 2018-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-15
      相关资源
      最近更新 更多