如何在TypeORM中实现聚合:统计订阅兴趣的客户数量
优化兴趣列表查询:仅统计订阅客户数量而非加载全部客户数据
问题场景
我需要获取兴趣列表及其相关数据,同时统计每个兴趣的订阅客户数量。兴趣与客户之间为多对一关系,目前实现的查询代码如下:
const list = await this.interestRepository .createQueryBuilder('interest') .leftJoinAndSelect("interest.translations", "translations") .leftJoinAndSelect("interest.customers", "customers") .getMany()
查询结果会返回每个兴趣的完整客户列表:
list [ Interest { id: 'YJnu_8bpzMSrFiztDl1zH', creationDate: 2022-12-19T16:49:55.090Z, countryCode: 'LTU', rank: 2, status: 'active', translations: [ [InterestTranslation], [InterestTranslation] ], customers: [ [Customer] ] }, Interest { id: '-h1UPpOSkw4TqcTc7F5Ej', creationDate: 2022-12-19T16:57:47.718Z, countryCode: 'USA', rank: 1, status: 'active', translations: [ [InterestTranslation], [InterestTranslation] ], customers: [] } ]
但客户可能多达数千,加载全部客户数据会影响请求耗时,因此希望仅统计客户数量而非加载全部数据。
优化方案
方案1:使用TypeORM内置关联统计API(推荐)
TypeORM提供了loadRelationCountAndMap方法,专门用于统计关联关系的数量,无需手动编写COUNT和分组逻辑,代码简洁高效:
const list = await this.interestRepository .createQueryBuilder('interest') .leftJoinAndSelect("interest.translations", "translations") // 将统计的客户数量映射到interest的customerCount属性上 .loadRelationCountAndMap('interest.customerCount', 'interest.customers') .getMany();
执行后,每个Interest对象会新增customerCount字段,直接显示该兴趣的订阅客户数,不会加载任何Customer实体数据。
方案2:手动编写COUNT统计查询
如果需要更灵活的查询控制,可以通过左连接+COUNT函数实现统计,同时分组确保每个兴趣只返回一条结果:
const result = await this.interestRepository .createQueryBuilder('interest') .leftJoinAndSelect("interest.translations", "translations") .leftJoin("interest.customers", "customers") // 统计客户数量 .addSelect('COUNT(DISTINCT customers.id)', 'customerCount') // 按兴趣主键分组,确保结果唯一 .groupBy('interest.id') // 若translations是一对多关联,需同时按translations主键分组(根据实际实体配置调整) .addGroupBy('translations.id') .getRawAndEntities(); // 结果拆分:entities是兴趣实体列表,raw包含统计的customerCount const { entities: interestList, raw } = result; // 可将统计值映射到实体上 interestList.forEach((interest, index) => { interest.customerCount = parseInt(raw[index].customerCount); });
内容的提问来源于stack exchange,提问作者Chicha
相关产品推荐
相关产品推荐

