如何用TypeORM QueryBuilder查询无关联或关联指定组的折扣方案?
使用QueryBuilder查询两类DiscountPlan:未关联任何分组或关联指定分组
针对你需求的两类DiscountPlan(未关联任何CustomerGroup、关联指定groupId的),可以通过TypeORM的QueryBuilder结合左连接和OR条件实现,以下是具体方案:
方案一:直接关联实体查询
这种方式利用实体间的关联关系,代码更直观:
import { getRepository } from "typeorm"; import { DiscountPlan } from "./entities/DiscountPlan"; async function fetchTargetDiscountPlans(targetGroupId: number) { const discountPlanRepo = getRepository(DiscountPlan); const plans = await discountPlanRepo .createQueryBuilder("dp") // 左连接CustomerGroup关联 .leftJoin("dp.groups", "cg") // 两个条件:要么未关联任何分组,要么关联了目标分组 .where("cg.id IS NULL") .orWhere("cg.id = :groupId", { groupId: targetGroupId }) // 去重,避免同一计划因关联多个分组被重复返回 .distinct(true) .getMany(); return plans; }
代码说明
leftJoin:使用左连接确保未关联任何分组的DiscountPlan也会被查询出来,这类数据对应的cg.id为null- 双条件组合:通过
OR同时满足两类需求 distinct(true):如果某个DiscountPlan同时关联了目标分组和其他分组,左连接会生成多条记录,去重后得到唯一的实体实例
方案二:直接操作中间表(更灵活)
如果需要更精细的控制,可以直接操作TypeORM自动生成的多对多中间表(默认表名格式为[实体名1]_[实体名2],比如discount_plan_customer_group,可通过@JoinTable({ name: '自定义表名' })指定):
import { getRepository } from "typeorm"; import { DiscountPlan } from "./entities/DiscountPlan"; async function fetchTargetDiscountPlans(targetGroupId: number) { const discountPlanRepo = getRepository(DiscountPlan); const plans = await discountPlanRepo .createQueryBuilder("dp") // 左连接到多对多中间表,替换成你实际的中间表名 .leftJoin( "discount_plan_customer_group", "dpcg", "dpcg.discountPlanId = dp.id" ) .where("dpcg.customerGroupId IS NULL") .orWhere("dpcg.customerGroupId = :groupId", { groupId: targetGroupId }) .distinct(true) .getMany(); return plans; }
注意事项
- 中间表的外键字段名默认是
[实体名小写]Id,比如discountPlanId和customerGroupId,如果在@JoinTable中自定义了外键名称,需要对应修改 - 若使用TypeORM 0.3.x版本,需将
getRepository替换为dataSource.getRepository,核心查询逻辑保持不变
内容的提问来源于stack exchange,提问作者soroush madani
相关产品推荐
相关产品推荐

