export default function (sequelize, DataTypes) {
const OrderAddress = sequelize.define('OrderAddress', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
is_default: {
type: DataTypes.BOOLEAN,
allowNull: true,
defaultValue: false,
},
receiver_name: {
type: DataTypes.STRING,
allowNull: true,
},
phone_number: {
type: DataTypes.STRING,
allowNull: true,
},
address: {
type: DataTypes.STRING,
allowNull: true,
},
address_detail: {
type: DataTypes.STRING,
allowNull: true,
},
postcode: {
type: DataTypes.STRING,
allowNull: true,
},
}
});
我的orderAddress
模型如上所示,我想进行验证以仅允许一个项目将is_default
设置为 true
。
所以
const address = {
is_default: true, // default one
}
const address2 = {
is_default: true // no you can't!
}
我应该is_default
字段unique: true
还是为此模型添加一些自定义validation
?
可能有几种方法可以实现这一点。
- Sequelize 为在查询生命周期中的特定事件上触发的钩子提供了一个选项。
使用beforeCreate
或afterValidate
钩子,您可以进行获取并查找是否有任何记录以is_default
作为true
,只需抛出错误即可。 - 在数据库层上添加一个触发器,该触发器检查是否有任何现有行带有
is_default
。可以通过后续迁移来添加和管理此类触发器
order_id
(或任何关系字段(和is_defualt
(第一个示例(上添加唯一索引,也可以对其进行一些重构以在Order
上设置default_address
,而不是在OrderAddress
上设置它(第二个示例(
第一个选项,添加唯一索引
// ...
indexes: [
{
fields: ['is_default', 'order_id'], // or whatever your relational field is
unique: true,
},
],
// ...
第二个选项,在订单级别检查
假设OrderAddress
属于类似Order
模型的东西,您还可以在此处添加验证以提高效率。由于您想知道哪个地址是默认地址,并且只允许一个地址,因此添加一个名为 Order.default_address
的字段并将值设置为"地址"或"address2"的枚举,指示应该使用哪个 - 自然只能设置一个,而不是两个。
然后,在Order
模型上,您可以添加一个beforeValidate
钩子,用于检查设置为"默认"的字段是否包含OrderAddress
的 ID。
export default function (sequelize, DataTypes) {
const Order = sequelize.define('Order', {
// your fields
default_address: {
type: DataTypes.ENUM(),
values: ['address', 'address2'],
allowNull: false,
// defaultValue: 'address',
},
{
hooks: {
beforeValidate: function(instance) {
switch (instance.default_address) {
case 'address':
case 'address2': {
// check to see if address_id or address2_id is set, as needed
if (!instance[instance.default_address + '_id') { // or + 'Id' if you use camel case
return Sequelize.Promise.reject(
new Error(`Default "${instance.default_address}" not set`)
);
}
}
default: {
return Sequelize.Promise.reject(
new Error('You must set a default address')
);
}
}
},
}
}
});