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

TypeORM查询时自定义计算列值如何通过getMany返回实体结果

TypeORM 自定义计算字段 getMany() 无法获取问题解决方案

问题根因

TypeORM 的 getMany() 方法会将查询结果自动映射到对应实体类的实例中,所有未在实体类中定义的字段会在映射阶段被直接丢弃;而 getRawMany() 直接返回数据库查询的原始结果,不做实体映射校验,因此可以正常拿到自定义计算的 points 字段。


方案1:在实体类中新增映射字段(推荐)

步骤1:修改ContractPoint实体类,新增points字段

TypeORM 0.3.x+ 版本可以使用@VirtualColumn标记为虚拟计算字段,不会持久化到数据库:

import { Entity, Column, VirtualColumn } from 'typeorm';

@Entity()
export class ContractPoint {
  // 原有其他字段保持不变
  // ...

  // 新增虚拟计算字段
  @VirtualColumn({ type: 'int' })
  points: number;
}

低于0.3.x的旧版本TypeORM,可以用普通@Column标记为非持久化字段:

@Column({ 
  type: 'int', 
  nullable: true, 
  select: false, 
  insert: false, 
  update: false 
})
points: number;

步骤2:修改查询语句,调整计算字段别名

按照TypeORM的实体映射别名规则,自定义字段别名需要遵循[实体别名]__[字段名]的格式,才能自动映射到实体属性:

const contractPoints = await getRepository(ContractPoint).createQueryBuilder('contractPoint')
      // 调整别名,匹配实体字段映射规则
      .addSelect(
        'contractPoint.point + COALESCE((SELECT SUM(cpHistory.point_change) FROM contract_point_history AS cpHistory WHERE cpHistory.contract_point_id = contractPoint.id), 0)', 
        'contractPoint__points'
      )
      .andWhere('EXTRACT(YEAR FROM contractPoint.validFrom) = :year', { year })
      .andWhere('contractPoint.contractId = :contractId', { contractId })
      .orderBy('contractPoint.grantedAt', OrderByDirection.Desc)
      .getMany();

修改后直接调用getMany()即可正常获取points字段。

方案2:不修改实体,手动合并字段

如果不想修改实体结构,可以使用getRawAndEntities()方法同时获取实体和原始查询结果,手动合并计算字段:

const { entities, raw } = await getRepository(ContractPoint).createQueryBuilder('contractPoint')
      .addSelect(
        'contractPoint.point + COALESCE((SELECT SUM(cpHistory.point_change) FROM contract_point_history AS cpHistory WHERE cpHistory.contract_point_id = contractPoint.id), 0)', 
        'points'
      )
      .andWhere('EXTRACT(YEAR FROM contractPoint.validFrom) = :year', { year })
      .andWhere('contractPoint.contractId = :contractId', { contractId })
      .orderBy('contractPoint.grantedAt', OrderByDirection.Desc)
      .getRawAndEntities();

// 手动合并计算字段到实体实例
const contractPoints = entities.map((entity, index) => ({
  ...entity,
  points: raw[index].points
}));

内容的提问来源于stack exchange,提问作者Daniyar Changylov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.18 12:45:04