如何在 Sequelize 中使用外键和常规键创建复合唯一约束?
Posted
技术标签:
【中文标题】如何在 Sequelize 中使用外键和常规键创建复合唯一约束?【英文标题】:How can I make a composite unique constraint with foreign keys and regular keys in Sequelize? 【发布时间】:2017-12-18 20:04:53 【问题描述】:我们有两个模型,用户和项目。在 User.js 下
User = Model.define('User',
id:
type: DataType.UUID,
defaultValue: DataType.UUIDV1,
primaryKey: true,
,
);
在 Item.js 下
Item = Model.define('Item',
id:
type: DataType.UUID,
defaultValue: DataType.UUIDV1,
primaryKey: true,
,
);
这是他们的关联,一个用户可以有很多项。
User.hasMany(Items,
foreignKey:
allowNull: false,
name: 'itemId',
,
onUpdate: 'cascade',
onDelete: 'cascade',
);
假设每个用户可能只有每种类型的项目之一。 如何为此添加唯一约束?以下代码不起作用。
User.hasMany(Items,
foreignKey:
allowNull: false,
name: 'itemId',
unique: 'userItemUnique',
,
onUpdate: 'cascade',
onDelete: 'cascade',
);
Item = Model.define('Item',
id:
type: DataType.UUID,
defaultValue: DataType.UUIDV1,
primaryKey: true,
unique: 'userItemUnique',
,
);
【问题讨论】:
【参考方案1】:您可以为此使用迁移。
Sequelize-cli 提供了 addConstraint 和 andIndex 方法,可以用来实现
来自docs
queryInterface.addConstraint('Users', ['email'],
type: 'unique', name: 'custom_unique_constraint_name'
);
【讨论】:
为什么一定要通过Sequelize-cli添加约束?有没有办法通过 Sequelize 本身来做到这一点? 你可以使用索引来做到这一点 [This](github.com/sequelize/sequelize/issues/3468) 问题的详细信息虽然这样做 imo 感觉不是很干净【参考方案2】:如果有人仍在关注此问题,我通过在需要唯一约束的模型中手动定义外键来解决此问题(您仍然可以使用 sequelize 关联,例如.hasMany
)。
关于您自己的代码,我认为当您请求 Assume that each user may only have one of each type of item
时可能会产生混淆,因为您没有定义什么是项目类型。
我根据自己的理解起草了一些内容,并考虑了我之前的评论。
User = Model.define('User',
id:
type: DataType.UUID,
defaultValue: DataType.UUIDV1,
primaryKey: true,
allowNull: false,
validate:
isUUID: 1,
,
,
);
Item = Model.define('Item',
id:
type: DataType.UUID,
defaultValue: DataType.UUIDV1,
primaryKey: true,
allowNull: false,
validate:
isUUID: 1,
,
,
type:
type: DataType.STRING,
unique: 'uniqueUserItemType' // see note 1
userId:
type: DataType.UUID,
references: // see note 2
model: User,
key: 'id',
,
unique: 'uniqueUserItemType',
);
User.hasMany(Item,
foreignKey:
allowNull: false,
name: 'itemId',
,
onUpdate: 'cascade',
onDelete: 'cascade',
);
Item.belongsTo(User);
我还按照 Sequelize 的建议添加了 belongsTo 关联。
[1] 关于复合唯一约束here的更多信息。
[2] 更多关于模型here 内部外键定义的信息。
【讨论】:
我唯一要补充的是,在定义中手动创建外键后,您可以像这样使用索引命令........索引:[唯一:真, fields: ['name','user_id'] ] 来创建复合键,这可以从我所看到的正确创建它。我将很快添加一个答案以更详细地展示这一点【参考方案3】:就我而言,我根据 Joel Barenco 的回答做了类似的事情。
const Model, DataTypes = require('sequelize');
const User = require('../models/user');
module.exports = function(sequelize)
class Algorithm extends Model
UserModel = User(sequelize);//@JA - Gets a defined version of user class
var AlgorithmFrame = Algorithm.init(
id:
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
,
name:
type: DataTypes.STRING,
allowNull: false,
,
user_Id:
type: DataTypes.INTEGER,
references:
model: UserModel,
key: 'id',
,
,
sequelize,
modelName: 'Algorithm',
indexes: [ unique: true, fields: ['name','user_id'] ]
);
return AlgorithmFrame
;
这里的想法是手动创建外键,但你可以用indexes: [ unique: true, fields: ['name','user_id'] ]
定义唯一索引
我的策略还展示了如何在类中定义模型。要调用它,您只需像这样将 sequelize 传递给它,其中 sequelize 是保存所有连接信息等的变量...
const Algorithm = require('../models/algorithm');
const AlogorithmModel = Algorithm(sequelize);
那么你可以确保它是用
创建的await AlogorithmModel.sync( alter: true );
我的用户模型文件是这样的:
const Model, DataTypes = require('sequelize');
module.exports = function(sequelize)
class User extends Model
return User.init(
id:
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
,
name:
type: DataTypes.STRING,
allowNull: false
,
trading_system_key:
type: DataTypes.STRING,
allowNull: false
,
,
sequelize,
modelName: 'User',
indexes: [ unique: true, fields: ['trading_system_key'] ]
);
;
【讨论】:
我不知道该怎么做的一件事是控制 onUpdate 和 onDelete,如果有人知道,请告诉我以上是关于如何在 Sequelize 中使用外键和常规键创建复合唯一约束?的主要内容,如果未能解决你的问题,请参考以下文章