Sequelizejs关联-外籍杰克-SegmentFault思否
one-to-one
看似一对一,其实一对多.这里的 one-to-one 指的应该是查询数据(主表)结果中,关联信息是以单个形式作为一个属性挂在主表每一个对象中
实际上是,主表与关联表的多对一关系.
belongsto
sourcemodel.belongsto(targetmodel, { as, foreignkey, targetkey })
拿 sourcemodel 中的 foreignkey 和 targetmodel 中的 targetkey 进行关联.
as 配置 targetmodel 的别名
foreignkey 配置 sourcemodel 中的外键字段名称,默认为 ${as || targetmodel.name}+${targetmodel.primarykey}
targetkey 配置 targetmodel 中的目标键字段名称,默认为 targetmodel 主键
查询出来结果结构如:
const sourceobj = { <sourceobjattr>: <value>, <sourceobjattr>: <value>, ... <as || targetmodel.name>: targetobj }
sourcemodel 中存在 foreignkey 关联 targetmodel,比如:
player.belongsto(team)
foreignkey 用来自定义 sourcemodel 中的外键名称.比如:
user.belongsto(company, { foreignkey: 'cid' }) // user.cid 即外键
默认情况下,foreignkey 值为${team.name}+${team.primarykey}.注意这里的连接是根据 source model 的配置而决定是 camelcase 还是 underscored.例如:
const user = this.sequelize.define('user', {}, { underscored: true }) const company = this.sequelize.define('company', { uuid: { type: sequelize.uuid, primarykey: true } }) user.belongsto(company) // user 的 foreignkey 为 company_uuid
targetkey 用来指定 targetmodel 中用来和 sourcemodel 中外键进行匹配的字段名称,默认为 targetmodel 中的 primarykey.比如:
user.belongsto(company, { foreignkey: 'cid', targetkey: 'uuid' }) // 即将 user.cid 与 company.uuid 进行关联
as 用来转换 targetmodel 的 name. 这里有两个方面,一个是在生成 foreignkey 时替换 targetmodel name,一个是在拼装查询结果时,改变 targetmodel 作为 sourcemodel 中的属性的名称.比如:
user.belongsto(company, { as: 'com' }) // foreign key would be: com_uuid // company property of user object would be 'com'
hasone
sourcemodel.hasone(targetmodel, { as, foreignkey })
拿 sourcemodel 中的主键和 targetmodel 中的外键进行关联
as 配置 targetmodel 的别名
foreignkey 配置 targetmodel 中的外键字段名称,默认为 ${as || sourcemodel.name}+${sourcemodel.primarykey}
查询结构为:
const sourceobj = { <sourceobjattr>: <value>, <sourceobjattr>: <value>, ... <as || targetmodel.name>: targetobj }
targetmodel 中存在 foreignkey 关联 sourcemodel,比如:
company.hasone(user)
foreignkey 默认为 ${company.name}+${company.primarykey}.也可以自定义:
company.hasone(user, { foreignkey: 'company_id' }) // user.company_id 为外键
targetkey hasone 中没有 targetkey 属性
belongsto v.s hasone
如果关联信息(比如:外键)保存在 source 中,就是用belongsto;如果关联信息保存在 target 中,则是用hasone
比如:
player 表,teamid 关联 team 表 coach 表 team 表,coachid 关联 coach 表player.belongsto(team) // player.teamid -- team.id coach.hasone(team) // team.coachid -- coach.id
为什么不能反过来,比如player.belongsto(team)中将 source 和 target 交换下,不就可以应用hasone了吗?问题就在于 source 是根据查询要求而定的,如果是要查询 player,并把关联的 team 信息带出来,那么 source 就只能是 player.
小结:根据查询主表,即 source,找到需要查询到的关联表,如果关联信息(外键)在 source 中,则 belongsto,否则 hasone.
one-to-many
hasmany
sourcemodel.hasmany(targetmodel, { as, foreignkey, sourcekey })
拿 targetmodel 中的外键与 sourcemodal 中的主键关联
as 配置 targetmodel 别名
foreignkey 配置 targetmodel 中外键名称,默认为 ${sourcemodel.name}+${sourcemode.primarykey}
sorucekey 配置 sourcemodel 中关联键名称,默认为 sourcemodel.primarykey
这里 as 的值并不影响 key 的默认值
many-to-many
belongstomany
sourcemodel.belongstomany(targetmodel, { through: associationmodel, as, foreignkey, otherkey })
通过中间表进行关联
as 中间表 associationmodel 的别名
foreignkey 配置 associationmodel 中与 sourcemodel 主键关联的外键名称,默认为 sourcemodel.name + sourcemodel.primarykey
otherkey 配置 associationmodel 中与 targetmodel 主键关联的外键名称,默认为 targetmodel.name + targetmodel.primarykey
这里 as 的值并不影响 key 的默认值
user.belongstomany(role, { through: roleassignment, foreignkey: 'userid', otherkey: 'roleid' }) user.findall({ include: [{ model: role, through: { // attributes: [], // uncomment this line to hide roleassignment as attribute in result in target model model: roleassignment, where } }] })
返回结果
const result = [{ id: '', username: '', gender: '', roles: [{ id: '', rolename: '', ... roleassignment: { id: '', roleid: '', userid: '', ... } }] }]