Sequelize关联查询:筛选匹配指定时间或无关联日历的服务
问题原因
当前查询使用required: false对Calendar表执行左连接,关联模型内配置的time:300过滤规则仅作用于关联的Calendar表查询,不会对主表Service的记录做过滤。
对于id=1的服务,其关联的Calendar记录time值为400,左连接时无法匹配time=300的条件,因此返回结果中它的Calendars字段为空数组,但Service主表行不会被剔除,最终导致不符合预期的记录被返回。
需求实际需要筛选满足任意以下条件的服务:
- 关联Calendar记录中存在time等于目标值的条目
- 无任何关联的Calendar记录
核心要排除的是「存在关联Calendar,但所有关联条目的time都不等于目标值」的服务,即测试数据中id=1的记录。
实现代码
推荐使用EXISTS子查询做过滤,逻辑清晰且不会破坏findAndCountAll的分页计数准确性,同时使用参数绑定避免SQL注入风险:
const { Op } = require('sequelize'); const targetTime = 300; let result = await Service.findAndCountAll({ where: { name: 'test', [Op.or]: [ // 匹配存在目标时间关联日历的服务 Sequelize.literal(`EXISTS ( SELECT 1 FROM Calendars WHERE Calendars.serviceID = Service.id AND Calendars.time = :targetTime )`), // 匹配无任何关联日历的服务 Sequelize.literal(`NOT EXISTS ( SELECT 1 FROM Calendars WHERE Calendars.serviceID = Service.id )`) ] }, include: [ { model: Calendar, required: false, // 关联结果仅返回匹配目标时间的日历条目 where: { time: targetTime } } ], replacements: { targetTime }, offset: 0, limit: 10, distinct: true });
结果校验
基于提供的测试数据,上述查询返回结果完全符合预期:
- id=0:存在time=300的关联日历,命中第一条规则,正常返回
- id=1:存在关联日历但time为400,不满足任何规则,被过滤
- id=2:无任何关联日历,命中第二条规则,正常返回
内容的提问来源于stack exchange,提问作者milad
相关产品推荐
相关产品推荐

