【问题标题】:How do I stop sequelize from creating an unwanted primary key when inserting data?如何在插入数据时阻止 sequelize 创建不需要的主键?
【发布时间】:2017-02-17 22:16:14
【问题描述】:

我有一个没有任何主键的续集模型:

module.exports = (sequelize, DataTypes) => {
  const usersDoors = sequelize.define('usersDoors',
    {
      user_uid: {
        type: DataTypes.UUID,
        allowNull: false,
      },
      door_uid: {
        type: DataTypes.UUID,
        allowNull: false,
      },
      property_manager_uid: {
        type: DataTypes.UUID,
        allowNull: true,
      },
      tenant_uid: {
        type: DataTypes.UUID,
        allowNull: true,
      },
      created_at: {
        type: DataTypes.INTEGER,
        allowNull: false,
      },
    },
    {
      tableName: 'users_doors',
      indexes: [
        {
          name: 'doors_users_indexes',
          unique: true,
          fields: ['user_uid', 'door_uid', 'property_manager_uid', 'tenant_uid'],
        },
      ],
      classMethods: {
        associate: (models) => {
          usersDoors.belongsTo(models.users, { foreignKey: 'user_uid' });
          usersDoors.belongsTo(models.doors, { foreignKey: 'door_uid' });
          usersDoors.belongsTo(models.propertyManagers, { foreignKey: 'property_manager_uid' });
          usersDoors.belongsTo(models.tenants, { foreignKey: 'tenant_uid' });
        },
      },
    });

  return usersDoors;
};

当我插入数据(通过 sequelize)时,sequelize 会向表中添加一个复合主键,其中包括前 2 列(user_uid 和 door_uid)。这破坏了我的东西,我不想要它。

如何在插入数据时阻止 sequelize 创建不需要的主键?

更多细节:

  • 方言:postgresql
  • sequelize(节点包)版本:3.30.2
  • postgresql 版本:psql(9.6.1,服务器 9.5.5)
  • 节点版本(这与任何事情无关):6.9.1

最后,这是此模型的 sequelize 迁移:

const tableName = 'users_doors';
module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.createTable(tableName, {
      user_uid: {
        type: Sequelize.UUID,
        allowNull: false,
        references: {
          model: 'users',
          key: 'uid',
        },
      },
      door_uid: {
        type: Sequelize.UUID,
        allowNull: false,
        references: {
          model: 'doors',
          key: 'uid',
        },
      },
      property_manager_uid: {
        type: Sequelize.UUID,
        allowNull: true,
        references: {
          model: 'property_managers',
          key: 'uid',
        },
      },
      tenant_uid: {
        type: Sequelize.UUID,
        allowNull: true,
        references: {
          model: 'tenants',
          key: 'uid',
        },
      },
      created_at: {
        type: Sequelize.INTEGER,
        allowNull: false,
      },
    })
      .then(() => {
        return queryInterface.addIndex('users_doors',
          ['user_uid', 'door_uid', 'property_manager_uid', 'tenant_uid'],
          {
            indexName: 'doors_users_indexes',
            indicesType: 'UNIQUE',
          });
      });
  },

  down: (queryInterface) => {
    return queryInterface.dropTable(tableName)
      .then(() => {
        return queryInterface.removeIndex('users_doors', ['user_uid', 'door_uid', 'property_manager_uid', 'tenant_uid']);
      });
  },
};

【问题讨论】:

    标签: node.js postgresql sequelize.js


    【解决方案1】:

    你只需要添加属性来续集模型,以及迁移,这将是你的主键

    // in sequelize model definition
    const usersDoors = sequelize.define('usersDoors',
    {
      id: {
          type: DataTypes.INTEGER,
          primaryKey: true,
          autoIncrement: true
      },
      user_uid: {
          type: DataTypes.UUID,
          allowNull: false,
      },
      // other fields
    
    // in the migrations file
    return queryInterface.createTable(tableName, {
      id: {
          type: Sequelize.INTEGER,
          primaryKey: true,
          autoIncrement: true
      },
      user_uid: {
          type: Sequelize.UUID,
          allowNull: false,
          references: {
              model: 'users',
              key: 'uid',
          },
      },
      // other fields
    

    根据文档,当您创建 M:M 关系时,sequelize 会自动创建一个主键,该主键由引用创建关系的表的两个外键组成(在您的情况下为 usersdoors

    该表将由两个表的键组合唯一标识

    编辑

    假设您在usersdoors 模型上都使用了belongsToMany,有一种方法可以避免在user_uiddoor_uid 上自动创建unique index。您需要在 m:m 关系初始化的 through 对象中指定 unique: false 条件(在两个模型中以避免任何自动唯一约束)

    // in users model
    users.belongsToMany(
        models.doors,
        {
            through: { model: models.usersDoors, unique: false },
            foreignKey: 'user_uid'
        }
    );
    
    // in doors model
    doors.belongsToMany(
        models.users,
        {
            through: { model: models.usersDoors, unique: false },
            foreignKey: 'door_uid'
        }
    );
    

    【讨论】:

    • 这种在 sequelize 中的工作不会创建额外的主键,但现在它在相同的 2 列上发明了一个唯一约束,你会注意到我实际上是唯一约束设置在 4 列上...
    • 我已经更新了关于自动unique约束的答案。
    • 我最终只是删除了 belongsToMany 关联,并将它们替换为多个 hasMany 和 belongsTo 关联。这解决了问题,现在剩下的唯一小问题是 sequelize 正在创建一个 id 列作为主键,这是我从未要求过的。这是我可以忍受的,但是因为我可以简单地忽略该列。您的解决方案是否也能防止这种不那么麻烦的问题发生?
    • usersDoors.removeAttribute('id') 怎么样?根据文档:“如果您的模型根本没有主键,您可以使用 Model.removeAttribute('id');”
    • 添加unique:false 是解决方案。它也适用于model.belongsTo 的情况。我在使用 include 选项时遇到了这个问题。我希望这会对某人有所帮助
    猜你喜欢
    • 1970-01-01
    • 2012-12-29
    • 2021-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-29
    • 1970-01-01
    • 2020-11-03
    相关资源
    最近更新 更多