解决sequelize在beforeToMany关联中的唯一约束

时间:2019-03-24 09:35:29

标签: database postgresql sequelize.js

我在项目中使用了Sequelize。这是两个模型:

const User = db.define('user', {
  name: Sequelize.STRING,
  password: Sequelize.STRING
})
const Product = db.define('product', {
  name: Sequelize.STRING,
  price: Sequelize.INTEGER
})

现在用户可以购买产品了,我的关联设置如下:

Product.belongsToMany(User, {through: 'UserProducts'})
User.belongsToMany(Product, {through: 'UserProducts'})

我也有此UserProducts表,其中有一个附加列。

const UserProducts = db.define('UserProducts', {
  status: Sequelize.STRING
})

Sequelize创建一个包含userId和productId组合的组合键,并且只允许包含userId和productId组合的一条记录。因此,例如,userId 2和productId14。

这对我来说是个问题,因为有时人们想多次购买。我需要以下方案之一才能工作:

  1. 不要使用复合键,而是将一个全新的自动增量列用作UserProducts中的键。

  2. 不是让我仅通过userId和productId来创建密钥,而是让我在诸如status之类的密钥中再添加一列,以便唯一密钥是这三个密钥的组合。

    < / li>

我确实想使用关联,因为它们提供了许多强大的方法,但是我想更改唯一键以使其能够以用户ID和产品ID相同的组合添加多行。

由于我的模型/数据库已经在运行,所以我需要利用迁移来进行此更改。

对此有任何帮助,我们深表感谢。

3 个答案:

答案 0 :(得分:3)

  

当模型中不存在主键时,Belongs-To-Many将创建一个唯一键。

由于UserProducts表中还具有其他属性,因此需要为UserProducts定义模型,然后告诉续集使用该模型,而不是创建自己的模型

class User extends Model {}
User.init({
    name: Sequelize.STRING,
    password: Sequelize.STRING
}, { sequelize })

class Product extends Model {}
ProjProductect.init({
    name: Sequelize.STRING,
    price: Sequelize.INTEGER
}, { sequelize })

class UserProducts extends Model {}
UserProducts.init({
  id: {
    type: Sequelize.INTEGER,
    primaryKey: true,
    autoIncrement: true
  },
  status: DataTypes.STRING
}, { sequelize })

User.belongsToMany(Project, { through: UserProducts })
Product.belongsToMany(User, { through: UserProducts })

引用:Sequelize v4 belongsToMany

更新

由于您正在使用v3,并且已经为您的UserProducts表创建了一个模型,因此需要使用以下代码段

UserProducts = db.define('UserProducts', {
  id: {
    type: Sequelize.INTEGER,
    primaryKey: true,
    autoIncrement: true
  },
  status: DataTypes.STRING
})

答案 1 :(得分:0)

如果其他任何人在 Sequelize v5中遇到问题,仅在“直通”模型上指定主键是不够的。
您必须在直通模型上显式设置唯一属性。

User.belongsToMany(Product, { through: { model: UserProducts, unique: false } });
Product.belongsToMany(User, { through: { model: UserProducts, unique: false } });

答案 2 :(得分:0)

由于在通过模型上显式设置唯一属性在 v6 中不起作用,我找到的唯一解决方案是以这种方式定义关联的 3 部分:

User.hasMany(UserProducts);
UserProducts.belongsTo(User);

Product.hasMany(UserProducts);
UserProducts.belongsTo(Product);

然后您可以创建模型和关联:

const user = await User.create(user_data);
const product = await Product.create(product_data);
const up = await UserProduct.create(up_data);
await up.setUser(user);
await up.setProduct(product);

如果有人有更好的解决方案,我很乐意知道