TypeORM子查询结合skip/take报错:无法获取别名sort的实体元数据
解决TypeORM分页时
Cannot get entity metadata for the given alias "sort"错误 问题原因
当使用skip()和take()进行分页时,TypeORM会严格校验查询语句中所有别名对应的实体元数据。你定义的sort是子查询生成的临时别名,并非对应任何已定义的Entity,因此触发元数据找不到的错误。而不使用分页时,TypeORM的校验逻辑相对宽松,所以查询能正常执行。
解决方案
方案1:改用getRawMany()手动映射结果
getMany()期望返回标准的Entity对象,而子查询的total字段不属于LazadaProduct实体结构,结合分页会触发校验失败。改用getRawMany()获取原始查询结果后,手动映射为实体对象:
// 执行原始查询 const rawResults = this.dataSource .getRepository(LazadaProduct) .createQueryBuilder('product') .leftJoin( subquery => { return subquery .from(LazadaProductSku, "sku") .select("sku.product_id", "sort_product_id") .addSelect("SUM(sku.quantity)", "total") .groupBy("sku.product_id") }, "sort", "sort.sort_product_id = product.id" ) .select(["product.*", "sort.total"]) // 明确指定需要查询的字段 .orderBy('sort."total"', body.sortValue as 'ASC' | 'DESC') .skip(skip) .take(limit) .getRawMany(); // 手动映射为LazadaProduct实体,可按需添加total字段 const products = rawResults.map(raw => { const product = Object.assign(new LazadaProduct(), raw); // 如果实体没有total字段,可添加为临时属性 product.totalStock = raw.total; return product; });
方案2:将求和子查询作为计算字段
避免左连接子查询,直接将库存求和作为实体的一个计算字段,这样TypeORM不会因为临时别名触发校验:
const products = this.dataSource .getRepository(LazadaProduct) .createQueryBuilder('product') .addSelect( (subquery) => { return subquery .select("SUM(sku.quantity)", "total") .from(LazadaProductSku, "sku") .where("sku.product_id = product.id"); }, "total" ) .orderBy('"total"', body.sortValue as 'ASC' | 'DESC') .skip(skip) .take(limit) .getRawMany(); // 同样需要用getRawMany获取包含total的结果,再映射
方案3:用leftJoinAndMapOne映射子查询到实体属性
如果你的LazadaProduct实体可以添加一个属性存储库存汇总,比如stockSummary,可以用leftJoinAndMapOne将子查询结果映射到该属性,让TypeORM识别这个关联:
首先定义一个简单的类用于存储汇总数据:
class StockSummary { total: number; }
然后修改查询语句:
const products = this.dataSource .getRepository(LazadaProduct) .createQueryBuilder('product') .leftJoinAndMapOne( "product.stockSummary", // 映射到实体的属性 (subquery) => { return subquery .from(LazadaProductSku, "sku") .select("sku.product_id", "product_id") .addSelect("SUM(sku.quantity)", "total") .groupBy("sku.product_id"); }, "sort", "sort.product_id = product.id" ) .orderBy('sort.total', body.sortValue as 'ASC' | 'DESC') .skip(skip) .take(limit) .getMany();
此时product.stockSummary.total就是该商品的总库存,TypeORM能正确识别映射关系,分页时不会报错。
内容的提问来源于stack exchange,提问作者Đức Long
相关产品推荐
相关产品推荐

