You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 15:05:25