sequelize: Keep getting unique validation error: How to allow duplicate entries in N:M (belongsToMany)?
The unique validation check is preventing me from creating duplicate entries in my join table:
// models/user.js
User.belongsToMany(models.item, { through: models.history, as: "Owners',
foreignKey: {
name: "itemId",
allowNull: true,
unique: false
}
});
// models/item.js
Item.belongsToMany(models.user, { through: models.history, as: "Owned",
foreignKey: {
unique: false
}
});
// models/history.js
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
other: DataTypes.STRING
When a user buys the same item again, resulting in duplicate combinations of itemId
and userId
in history
table, sequelize will throw validation errors:
{ name: 'SequelizeUniqueConstraintError',
message: 'Validation error',
....
message: "userId" must be unique
type: 'unique violation'
....
message: "itemId" must be unique
type: 'unique violation'
But I have set unique: false
on the foreignkeys, and have created a primaryKey for history
table, so this validation error confused me. What’s the proper way to allow duplicate entries in N:M?
About this issue
- Original URL
- State: open
- Created 9 years ago
- Comments: 34 (8 by maintainers)
Commits related to this issue
- Change model to avoid foreign key - There's a bug in Sequelize "BelongsToMany" where it refuses to accept multiple foreign keys ("user_id and photo_id must be unique"), but this is not correct error ... — committed to amadk/escape-reality by deleted user 8 years ago
- Change model to avoid foreign key - There's a bug in Sequelize "BelongsToMany" where it refuses to accept multiple foreign keys ("user_id and photo_id must be unique"), but this is not correct error ... — committed to lowtalkers/escape-reality by deleted user 8 years ago
I met the same thing: unique: false does not prevents creation of unique index. First I came to google and found this post. And I’ve tried as @mickhansen said:
But this is not correct. After deep debugging I’ve found that belongsToMany expects the complex object ‘through’ if we want to set additional options to the relation. So the correct code is:
Item.belongsToMany(models.user, { through: { model: models.history, as: "Owned", unique: false}});
As I’ve found this, I search the sequel docs for word ‘unique’. And found this feature in n:m chapter: http://docs.sequelizejs.com/en/latest/docs/associations/?highlight=unique: false#nm
See the example for Post:
P.S. Maybe this options may be covered in manual more clearly. I’ve read man several times, but ‘unique: false’ feature was discovered only with Google.
This should be mentioned in docs very explicitly.
For anyone with this issue, here is a suggested workaround:
However the solution above of course will change how you fundamentally perform includes and the like.
This code will help you. Look at this: I have found that primaryKey must be false and I did it with adding to my associations
primaryKey: false
Main thing there primaryKey must be false And I didn’t optimize my code, you can do it 😃
The unique constraint error deletes the previous records too. This isn’t expected. Please resolve the issue
Hi, is this still ongoing?
I need the relation table to avoid having a composite primary key with the 2 relation fields, is that possible?
Perhaps we can give it the field name for the primary key?
Shall I need to create my own model for this and then set unique: false on the BelongsToMany ?
Forgive me if this a noob thing to say, I’m new to Sequelize and am a little rusty on SQL, but it looks like when you create
belongsToMany
tables, for example:It’s using the
productId, userId
together as the primary key. While this could work fine for pure unique relationships, it doesn’t handle the circumstances where the same relation can be created multiple times - because the primary key has to be unique.For example, purchasing/viewing the same product multiple times.
To get around this I’ve created a separate
id
primary key on the relational table, using an auto increment.Don’t know if this is the best solution but it certainly works.
unique entries in N:M is currently not supported. You can use
unique: false
for the options on the N:M relation but it only gets you halfway there (the setters will not work ideally so you manually have to create entries).