Association
直接子类
在 Sequelize 中创建关联是通过在模型(源)上调用 belongsTo / hasOne / hasMany / belongsToMany 函数之一,并提供另一个模型作为函数的第一个参数(目标)来完成的。
- hasOne - 在目标模型中添加外键,并在源模型中添加单数关联mixin。
- belongsTo - 在源模型中添加外键和单数关联mixin。
- hasMany - 在目标模型中添加外键,并在源模型中添加复数关联mixin。
- belongsToMany - 创建一个N:M关联,使用连接表,并在源模型中添加复数关联mixin。连接表使用sourceId和targetId创建。
创建关联会在属性中添加外键约束。所有关联在更新时使用CASCADE
,在删除时使用SET NULL
,除了n:m关联,它在删除时也使用CASCADE
。
创建关联时,可以通过as
选项提供别名。当同一个模型关联两次,或者希望关联的名称与目标模型的名称不同时,这很有用。
例如,考虑用户拥有多个图片,其中一个图片是用户个人资料图片的情况。所有图片都有一个userId
,但是用户模型还有一个profilePictureId
,以便能够轻松加载用户的个人资料图片。
User.hasMany(Picture)
User.belongsTo(Picture, { as: 'ProfilePicture', constraints: false })
user.getPictures() // gets you all pictures
user.getProfilePicture() // gets you only the profile picture
User.findAll({
where: ...,
include: [
{ model: Picture }, // load all pictures
{ model: Picture, as: 'ProfilePicture' }, // load the profile picture.
// Notice that the spelling must be the exact same as the one in the association
]
})
要完全控制Sequelize添加的外键列,可以使用foreignKey
选项。它可以是一个字符串,指定列名,也可以是一个对象类型定义,等同于传递给sequelize.define
的那些。
User.hasMany(Picture, { foreignKey: 'uid' })
现在,Picture中的外键列将被称为uid
,而不是默认的userId
。
User.hasMany(Picture, {
foreignKey: {
name: 'uid',
allowNull: false
}
})
这指定了uid
列不能为null。在大多数情况下,这已经由Sequelize自动创建的外键约束覆盖,但在外键被禁用时(例如,由于循环引用(参见下面的constraints: false
))可能会很有用。
获取关联模型时,可以将查询限制为仅加载一些模型。这些查询的写法与find
/findAll
的查询相同。要仅获取JPG格式的图片,可以执行以下操作
user.getPictures({
where: {
format: 'jpg'
}
})
更新和添加新的关联有几种方法。继续我们关于用户和图片的例子
user.addPicture(p) // Add a single picture
user.setPictures([p1, p2]) // Associate user with ONLY these two picture, all other associations will be deleted
user.addPictures([p1, p2]) // Associate user with these two pictures, but don't touch any current associations
如果关联模型只有一个主键,则不必将完整对象传递给关联函数。
user.addPicture(req.query.pid) // Here pid is just an integer, representing the primary key of the picture
在上面的例子中,我们指定了一个用户属于他的个人资料图片。从概念上讲,这可能没有意义,但由于我们希望将外键添加到用户模型中,所以这是实现的方法。
注意我们也为个人资料图片指定了constraints: false
。这是因为我们从用户到图片(profilePictureId)添加了一个外键,并且从图片到用户(userId)添加了一个外键。如果我们同时为两者添加外键,则会创建一个循环依赖关系,Sequelize将不知道先创建哪个表,因为用户依赖于图片,而图片依赖于用户。这些问题会在模型同步到数据库之前由Sequelize检测到,您将收到类似于Error: Cyclic dependency found. 'users' is dependent of itself
的错误。如果您遇到这种情况,则应禁用一些约束,或完全重新思考您的关联关系。