使用 Sequelize 实现单一 Table 继承
Achieve Single Table Inheritance with Sequelize
有没有办法使用 sequelize 创建单个 table 继承?
我想要一个用于购买和部分购买模型的 STI,其中我将有一个类型字段,它是 "Purchase" 或 "PartialPurchase" 和 classes 购买和部分购买每个都继承自 Operation class.
我认为 sequelize 不支持此功能,但是否可以实现?
嘿,所以我知道你没有在合理的时间内得到答案,但你可以像你说的那样在你的数据库中使用一个枚举类型列,然后使用 sequelize 的范围功能。 Scope 在从查询到模型定义和关联的所有方面都起作用。结果很好。我为带有请求和响应的消息 table 实现了类似的东西。
module.exports = function(sequelize, DataTypes) {
var Message = sequelize.define('Message', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER,
},
type: {
type: DataTypes.ENUM('REQUEST', 'RESPONSE', 'FILE'),
allowNull: false
},
text: {
type: DataTypes.TEXT,
allowNull: false,
},
state: {
type: DataTypes.JSONB,
allowNull: true,
},
userTeamId: {
type: DataTypes.INTEGER,
allowNull: false,
}
}, );
Message.associate = (models) => {
Message.belongsTo(models.UserTeam, { foreignKey: 'userTeamId', targetKey: 'tag'})
}
return Message;
};
这就是我做联想的方式。
module.exports = function(sequelize, DataTypes) {
var UserTeam = sequelize.define('UserTeam', {
tag: { type: DataTypes.UUID, allowNull: false, unique: true},
active: { type: DataTypes.BOOLEAN, defaultValue: false },
activationNonce: { type: DataTypes.STRING },
UserId: { type: DataTypes.INTEGER, },
TeamId: { type: DataTypes.INTEGER, },
type: DataTypes.ENUM('OWNER', 'ADMIN', 'MEMBER', 'GUEST'),
},);
UserTeam.associate = (models) => {
UserTeam.hasMany(models.Message, { as: 'responses', foreignKey: 'userTeamId', sourceKey: 'tag', scope: {type: 'RESPONSE'}})
UserTeam.hasMany(models.Message, { as: 'requests', foreignKey: 'userTeamId', sourceKey: 'tag', scope: {type: 'REQUEST'}})
UserTeam.hasMany(models.Message, { as: 'files', foreignKey: 'userTeamId', sourceKey: 'tag', scope: {type: 'FILE'}})
UserTeam.hasOne(models.Team, {foreignKey: 'id', sourceKey: 'TeamId'})
UserTeam.belongsTo(models.User, {foreignKey: 'UserId', sourceKey: 'id'})
}
return UserTeam;
};
关联的好处在于,您可以使用 UserTeam 实例执行操作,例如 'userteam.getFiles()' 以获取所有关联文件。
我认为尚不支持此功能 (09/2021)。但是,我现在正在为此寻找解决方案。下面的例子解决了两个需求:
- 我们有两个实体在同一个table(继承和添加新属性)和;
- 有一种方法可以使所有模型具有共同的属性:
const ModelDiscriminators = {
Dish: 1,
Item: 2,
ItemWithEmail: 3
}
//Basic field attributes for all entities
const BasicModelAttributes = {
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }
};
//Table dish have id, name, veg, discriminator attributes
const Dish = sequelize.define('dish', Object.assign( {}, BasicModelAttributes, {
name: { type: DataTypes.STRING },
veg: { type: DataTypes.BOOLEAN },
discriminator: { type: DataTypes.INTEGER, defaultValue: () => ModelDiscriminators.Dish }
} ) );
//Two entities sharing same table. Table Item has id, name, type, discriminator e email(see model ItemWithEmail) atributes
//Model Item
const Item = sequelize.define('item', Object.assign( {}, BasicModelAttributes, {
name: { type: DataTypes.STRING },
type: { type: DataTypes.STRING },
discriminator: { type: DataTypes.INTEGER, defaultValue: () => ModelDiscriminators.Item }
} ) );
//Model ItemWithEmail inherits all Item attributes and define a new one: e-mail
//We use the discriminator attribute to query the right records when we make a query or .findAll(+where)
const ItemWithEmail = sequelize.define('item', Object.assign({}, Item.rawAttributes, {
email: { type: DataTypes.STRING },
discriminator: { type: DataTypes.INTEGER, defaultValue: () => ModelDiscriminators.ItemWithEmail }
} ) );
我认为这种方法可能是 Sequelize 支持的默认方式。我们可以有一个继承关系,所以我们可以写:
ItemWithEmail.inherits( Item )
如有任何疑问,我很乐意再次为您提供帮助。 heltongoncalves@gmail.com
有没有办法使用 sequelize 创建单个 table 继承?
我想要一个用于购买和部分购买模型的 STI,其中我将有一个类型字段,它是 "Purchase" 或 "PartialPurchase" 和 classes 购买和部分购买每个都继承自 Operation class.
我认为 sequelize 不支持此功能,但是否可以实现?
嘿,所以我知道你没有在合理的时间内得到答案,但你可以像你说的那样在你的数据库中使用一个枚举类型列,然后使用 sequelize 的范围功能。 Scope 在从查询到模型定义和关联的所有方面都起作用。结果很好。我为带有请求和响应的消息 table 实现了类似的东西。
module.exports = function(sequelize, DataTypes) {
var Message = sequelize.define('Message', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER,
},
type: {
type: DataTypes.ENUM('REQUEST', 'RESPONSE', 'FILE'),
allowNull: false
},
text: {
type: DataTypes.TEXT,
allowNull: false,
},
state: {
type: DataTypes.JSONB,
allowNull: true,
},
userTeamId: {
type: DataTypes.INTEGER,
allowNull: false,
}
}, );
Message.associate = (models) => {
Message.belongsTo(models.UserTeam, { foreignKey: 'userTeamId', targetKey: 'tag'})
}
return Message;
};
这就是我做联想的方式。
module.exports = function(sequelize, DataTypes) {
var UserTeam = sequelize.define('UserTeam', {
tag: { type: DataTypes.UUID, allowNull: false, unique: true},
active: { type: DataTypes.BOOLEAN, defaultValue: false },
activationNonce: { type: DataTypes.STRING },
UserId: { type: DataTypes.INTEGER, },
TeamId: { type: DataTypes.INTEGER, },
type: DataTypes.ENUM('OWNER', 'ADMIN', 'MEMBER', 'GUEST'),
},);
UserTeam.associate = (models) => {
UserTeam.hasMany(models.Message, { as: 'responses', foreignKey: 'userTeamId', sourceKey: 'tag', scope: {type: 'RESPONSE'}})
UserTeam.hasMany(models.Message, { as: 'requests', foreignKey: 'userTeamId', sourceKey: 'tag', scope: {type: 'REQUEST'}})
UserTeam.hasMany(models.Message, { as: 'files', foreignKey: 'userTeamId', sourceKey: 'tag', scope: {type: 'FILE'}})
UserTeam.hasOne(models.Team, {foreignKey: 'id', sourceKey: 'TeamId'})
UserTeam.belongsTo(models.User, {foreignKey: 'UserId', sourceKey: 'id'})
}
return UserTeam;
};
关联的好处在于,您可以使用 UserTeam 实例执行操作,例如 'userteam.getFiles()' 以获取所有关联文件。
我认为尚不支持此功能 (09/2021)。但是,我现在正在为此寻找解决方案。下面的例子解决了两个需求:
- 我们有两个实体在同一个table(继承和添加新属性)和;
- 有一种方法可以使所有模型具有共同的属性:
const ModelDiscriminators = {
Dish: 1,
Item: 2,
ItemWithEmail: 3
}
//Basic field attributes for all entities
const BasicModelAttributes = {
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }
};
//Table dish have id, name, veg, discriminator attributes
const Dish = sequelize.define('dish', Object.assign( {}, BasicModelAttributes, {
name: { type: DataTypes.STRING },
veg: { type: DataTypes.BOOLEAN },
discriminator: { type: DataTypes.INTEGER, defaultValue: () => ModelDiscriminators.Dish }
} ) );
//Two entities sharing same table. Table Item has id, name, type, discriminator e email(see model ItemWithEmail) atributes
//Model Item
const Item = sequelize.define('item', Object.assign( {}, BasicModelAttributes, {
name: { type: DataTypes.STRING },
type: { type: DataTypes.STRING },
discriminator: { type: DataTypes.INTEGER, defaultValue: () => ModelDiscriminators.Item }
} ) );
//Model ItemWithEmail inherits all Item attributes and define a new one: e-mail
//We use the discriminator attribute to query the right records when we make a query or .findAll(+where)
const ItemWithEmail = sequelize.define('item', Object.assign({}, Item.rawAttributes, {
email: { type: DataTypes.STRING },
discriminator: { type: DataTypes.INTEGER, defaultValue: () => ModelDiscriminators.ItemWithEmail }
} ) );
我认为这种方法可能是 Sequelize 支持的默认方式。我们可以有一个继承关系,所以我们可以写:
ItemWithEmail.inherits( Item )
如有任何疑问,我很乐意再次为您提供帮助。 heltongoncalves@gmail.com