如何让TypeORM查询多对多关联返回未合并的重复实体结果?
解决TypeORM多对多关联查询结果自动归组的问题
在TypeORM中查询多对多关联的实体时,框架默认会将同一主实体的关联项归组成数组,这和原生SQL的返回结构差异很大。如果你需要让每条主实体记录对应一个关联实体(像原生查询那样),可以用以下方法:
方法1:使用getRawMany()获取原始结果并手动转换
TypeORM的getMany()会自动做结果归组(hydration),而getRawMany()会直接返回SQL查询的原始行数据,不会进行实体映射。你可以先拿到原始数据,再转换成期望的结构:
// 构建查询,支持添加任意查询条件、排序逻辑 const rawData = await getConnection() .createQueryBuilder(Product, "product") .select("product.id", "id") .addSelect("medic.id", "medic_id") .leftJoin("product.medics", "medic") .where("product.id = :id", { id: 1 }) .orderBy("medic.id", "ASC") .getRawMany(); // 转换为期望的结构 const formattedProducts = rawData.map(item => ({ id: item.id, medic: { id: item.medic_id } }));
转换后得到的结构与你的期望完全一致:
{ "products": [ { "id": 1, "medic": { "id": 1 } }, { "id": 1, "medic": { "id": 2 } }, { "id": 1, "medic": { "id": 3 } } ] }
为什么leftJoinAndMapOne不适用?
leftJoinAndMapOne的作用是将关联实体映射到主实体的单个属性上,但它只会取第一个匹配的关联项,无法返回所有关联对应的行,所以不符合需求。
优势
这种方法既保留了QueryBuilder灵活添加查询参数、排序、多关联查询的能力,又能得到和原生SQL一致的行结构,不需要完全重写成原生SQL。
内容的提问来源于stack exchange,提问作者nickfera
相关产品推荐
相关产品推荐

