Sequelize多对多关联中间表设置别名及字段合并方案咨询
这个需求完全可以通过Sequelize原生配置实现,不需要额外编写返回结果重命名逻辑,有两种常见实现方案:
方案1:直接将中间表字段平铺到Item属性中(推荐)
该方案可以完全去掉中间表嵌套层级,seen、owned字段会直接作为Item的根属性返回,和其他Item原生字段同级。
修改查询代码如下:
User.findByPk(id, { include: { model: db.Item, as: 'items', // 隐藏中间表默认返回的嵌套结构 through: { attributes: [] } }, attributes: [ // 这里保留你需要返回的User字段,不需要的话可以只保留主键 'id', // 映射中间表字段为Item的同级属性 [sequelize.col('items.UserItems.seen'), 'items.seen'], [sequelize.col('items.UserItems.owned'), 'items.owned'] ], order: [[sequelize.literal('"items"."dexId"'), 'ASC']], // 开启raw和nest才能让字段别名映射生效,自动生成嵌套结构 raw: true, nest: true }) .then(data => { res.status(200).json({ items: data.items}); }) .catch(err => { console.log(err); res.status(204).json({ items: []}); });
查询Guest关联的Item时,只需要把上面的items.UserItems.seen替换为items.GuestItems.seen即可,返回结构完全一致。
如果不需要返回User本身的任何字段,更推荐直接从Item侧发起查询,写法更简洁:
db.Item.findAll({ attributes: [ // 保留Item所有原生字段 ...Object.keys(db.Item.rawAttributes), // 直接映射中间表字段为Item属性 [sequelize.col('UserItems.seen'), 'seen'], [sequelize.col('UserItems.owned'), 'owned'] ], include: { model: db.UserItems, attributes: [], where: { userId: id } }, order: [['dexId', 'ASC']], raw: true }) .then(items => res.status(200).json({ items })) .catch(err => res.status(204).json({ items: [] }))
方案2:保留嵌套结构,统一中间表别名
如果需要保留嵌套层级,只需要将不同中间表的返回别名统一即可,在through配置中添加as参数:
// 查询User关联Item时 include: { model: db.Item, as: 'items', through: { attributes: ['seen', 'owned'], // 统一嵌套层级的键名,Guest查询时也用同一个别名 as: 'itemMeta' } }
这样不管是User还是Guest发起的查询,中间表字段都会嵌套在itemMeta属性下,不会出现UserItems、GuestItems的不同键名。
内容的提问来源于stack exchange,提问作者Jon
相关产品推荐
相关产品推荐

