如何扩展 Sequelize 模型?
Posted
技术标签:
【中文标题】如何扩展 Sequelize 模型?【英文标题】:How to extend a Sequelize model? 【发布时间】:2018-05-11 17:03:27 【问题描述】:有没有一种方法可以让我使用一个基类,该基类具有我的模型的所有公共属性和方法,但不与数据库表链接,然后我可以在定义新模型时扩展这个基类。
在这里,我在 node express 中创建了基本的 person 模型。我需要从基类扩展 person 类。
const person = sequelizeClient.define('person',
name:
type: DataTypes.STRING,
allowNull: false
,
hooks:
beforeCount(options)
options.raw = true;
);
const base = sequelizeClient.define('base',
id:
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true
,
createdBy:
type: Sequelize.INTEGER,
,
updatedBy:
type: Sequelize.INTEGER,
,
deletedBy:
type: Sequelize.INTEGER,
,
hooks:
beforeCount(options)
options.raw = true;
);
在文档中说
Sequelize 模型是 ES6 类。您可以非常轻松地添加自定义实例或类级别的方法。
如何使用 ES6 扩展类模式来做到这一点?
有一个类似的问题,但最近没有更新。 How to extend Sequelize model
【问题讨论】:
你使用的是什么版本的 Sequelize? 续集版本为v4.23.1 【参考方案1】:如何使用 ES6 扩展类模式来做到这一点?
Sequelize 文档中的声明让开发人员有点困惑。这并不意味着您可以使用 ES6 类语法扩展定义的模型,如下所示。
const User = db.define('User',
name: sequelize.STRING,
age: sequelize.INTEGER
);
// This is impossible.
class Staff extends User
...
但您可以通过访问原型来定义实例方法,如下所示。
const User = db.define('User',
name: sequelize.STRING,
age: sequelize.INTEGER
);
User.Instance.prototype.test = function()
return `Name: $this.name, Age: $this.age`
User.create( name: "John", age: 10 );
User.findOne().then((user) =>
console.log(user.test()) // "Name: John, Age: 10"
);
您在 Sequelize 文档中提到的声明实际上是说您可以使用 prototype based 扩展来增强模型行为,因此您不能执行您在问题中尝试执行的模型继承之类的事情。
关于ES6类语法在Sequelize中的实现提案有很多讨论,比如this,但看起来还在讨论中。
【讨论】:
你能举个例子,基本属性是通过基于原型的扩展继承的吗? 我在回答中给了你一个例子。User.Instance.prototype.test = function ...
的行就是那个。
如果不是太麻烦,请您在这里解释一下“实例”一词的用法。而且我想做的是定义一个带有属性和钩子的javascript对象,并使用该对象来定义所有其他模型,同时添加或覆盖方法和属性。
我很确定这是可能的,但我没有机会进一步调查。答案包含适用于 Sequelize v3 的旧 PR 的链接,而当前版本是 v4。
@estus 我尝试了类似class Staff extends User ...
的方法,但出现错误。我们可以看到任何文档或问题吗?【参考方案2】:
Sequelize 似乎无法扩展类模型,那么扩展 sequelize 对象的 config 对象怎么样?它的工作量稍大一些,但提供了最接近的体验并保持相对清洁。当然,同时使用 attributes
和 options
参数需要使用 2 个单独的类或对组合类进行适当的解构。
class Base
constructor()
this.id =
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true
;
...
class Person extends Base
constructor()
super();
this.name =
type: DataTypes.STRING,
allowNull: false
;
...
// using separate class for attributes
const person = sequelize.define('person', new Person());
// possible destructuring of attributes/options
const someModel= sequelize.define('someModel', (new SomeModel()).attributes, (new SomeModel()).options);
【讨论】:
【参考方案3】:我认为尚不支持此功能 (09/2021)。但是,我现在正在为此寻找解决方案。下面的例子解决了两个需求:
-
我们在同一个表中有两个实体(继承和添加新属性)并且;
有一种方法可以让所有模型都有共同的属性:
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 )
【讨论】:
以上是关于如何扩展 Sequelize 模型?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 sequelize 基于 sqlite3 中的“日期”列进行查询?