如何在Sequelize中查询关联表是否存在记录并返回标识
问题描述
我有一个ModelA模型,与ModelB模型存在一对多(1:N)关联。我想要获取ModelA的所有记录,同时返回一个布尔值:若存在至少一条关联的ModelB记录则为true,否则为false。
关联关系定义如下:
ModelA.hasMany(ModelB) ModelB.belongsTo(ModelA)
当前使用的查询语句:
const results = await ModelA.findAll({ include: { model: ModelB, required: false } })
该方式通过左外连接(outer join)可获取存在的ModelB匹配记录,但我并不关心ModelB的具体记录,仅需知道其是否存在。是否有办法生成对应的SELECT查询语句,直接根据连接结果返回true/false?
我期望的查询语句如下:
SELECT a.*, CASE WHEN b.id IS NOT NULL THEN true ELSE false END FROM modelA a LEFT OUTER JOIN modelB b on b.model_a_id = a.id
解决方案
方法一:用literal实现你期望的CASE逻辑
通过在查询的attributes中添加自定义字段,结合sequelize.literal生成目标SQL,同时分组避免左连接导致的重复记录:
const results = await ModelA.findAll({ attributes: [ // 保留ModelA的所有字段 ...Object.keys(ModelA.rawAttributes).map(key => `ModelA.${key}`), // 生成布尔字段hasModelB [sequelize.literal('CASE WHEN "ModelB"."id" IS NOT NULL THEN true ELSE false END'), 'hasModelB'] ], include: { model: ModelB, required: false, attributes: [] // 不加载ModelB的任何字段 }, group: ['ModelA.id'] // 按ModelA主键分组,去重 })
方法二:用EXISTS子查询(性能更优)
左连接会返回匹配的ModelB记录再去重,而EXISTS只需判断是否存在关联记录,性能更高效:
const results = await ModelA.findAll({ attributes: [ ...Object.keys(ModelA.rawAttributes).map(key => `ModelA.${key}`), [sequelize.literal('EXISTS(SELECT 1 FROM "ModelB" WHERE "ModelB"."model_a_id" = "ModelA"."id")'), 'hasModelB'] ] })
对应的SQL为:
SELECT "ModelA".*, EXISTS(SELECT 1 FROM "ModelB" WHERE "ModelB"."model_a_id" = "ModelA"."id") AS "hasModelB" FROM "ModelA";
内容的提问来源于stack exchange,提问作者Nicolas
相关产品推荐
相关产品推荐

