TypeORM左连接查询结果扁平化:QueryBuilder实现方案咨询
NestJS + TypeORM QueryBuilder 实现查询结果扁平化
我在NestJS中使用TypeORM操作MySQL数据库,拥有post、assets_post、asset三张表。当前编写的QueryBuilder查询返回嵌套结构,但我想直接在QueryBuilder中实现结果扁平化,无需查询后手动映射。
当前查询代码
private getAllQueryProcess( request: PostRequestDto, ): SelectQueryBuilder<PostEntity> { const queryBuilder = this.postEntity.createQueryBuilder('p'); queryBuilder.where('p.id is not null'); queryBuilder.leftJoinAndMapOne( 'p.id', AssetsPostEntity, 'ap', 'ap.post = p.id', ); queryBuilder.leftJoinAndMapOne( 'ap.asset', AssetEntity, 'a', 'a.id = ap.asset', ); queryBuilder.select([ 'p.id', 'p.title', 'ap.asset', 'ap.post', 'a.url', ]); queryBuilder.groupBy('p.id'); queryBuilder.orderBy('p.id', 'ASC'); return queryBuilder; }
当前返回的嵌套结果
{ "id": { "asset": { "url": "https://url" }, "post": 3 }, "title": "Some title", }
期望的扁平化结果
{ "id": 3, // 来自post表的id "url": "https://url", // 来自asset表的url "title": "Some title", }
解决方案
问题根源在于使用了leftJoinAndMapOne方法,它会将关联表的数据映射到主实体的属性上,从而产生嵌套结构。要实现扁平化,需要调整关联方式和字段选择逻辑:
private getAllQueryProcess( request: PostRequestDto, ): SelectQueryBuilder<PostEntity> { const queryBuilder = this.postEntity.createQueryBuilder('p'); // 改用普通leftJoin,避免自动映射嵌套结构 queryBuilder.leftJoin(AssetsPostEntity, 'ap', 'ap.post = p.id'); queryBuilder.leftJoin(AssetEntity, 'a', 'a.id = ap.asset'); // 直接选择需要的字段,用AS指定与期望结果一致的键名 queryBuilder.select([ 'p.id AS id', 'p.title AS title', 'a.url AS url', ]); queryBuilder.where('p.id IS NOT NULL'); queryBuilder.groupBy('p.id'); queryBuilder.orderBy('p.id', 'ASC'); return queryBuilder; }
关键说明
- 替换
leftJoinAndMapOne为leftJoin:普通leftJoin仅建立表关联,不会修改主实体的结构,避免产生嵌套。 - 字段别名配置:通过
AS将数据库字段直接映射为结果对象的扁平键名,确保输出结构符合预期。 - 获取结果的方式:调用该方法后,使用
getRawMany()而非getMany()获取结果,因为getRawMany()会直接返回数据库查询的原始扁平对象,而getMany()会尝试映射到实体类,可能保留不必要的结构。示例:const flatPosts = await this.getAllQueryProcess(request).getRawMany();
内容的提问来源于stack exchange,提问作者Duy Hưng Androgyne Tenor
相关产品推荐
相关产品推荐

