TypeORM查询Toy实体:如何仅关联用户名且剔除冗余关联字段?
解决方案
方案一:返回实体对象并转换user字段
利用getMany()获取实体实例,再通过映射将user关联转换为单独的username字段,可按需过滤外键属性:
async findAll() { // 获取Toy实体元数据,用于动态处理字段 const toyMetadata = this.toyRepository.metadata; // 提取所有非外键属性名(可选,若需排除userId、manufacturerId这类外键则启用) const nonForeignKeyProps = toyMetadata.columns .filter(col => !col.isForeignKey) .map(col => col.propertyName); // 查询Toy实体及关联的user用户名 const toys = await this.toyRepository .createQueryBuilder('toy') .select(['toy', 'userEntity.username']) // 选择Toy所有属性和user的username .leftJoin('toy.user', 'userEntity') .where('toy.deleted != :deleted', { deleted: true }) .getMany(); // 转换结果:将user对象转为username字符串,按需过滤外键 return toys.map(toy => { const processedToy = {}; // 若要保留Toy所有属性,直接替换为`const processedToy = { ...toy };` nonForeignKeyProps.forEach(prop => { processedToy[prop] = toy[prop]; }); processedToy['user'] = toy.user?.username; return processedToy; }); }
方案二:用元数据动态选择字段,返回结构化结果
通过实体元数据动态获取需要的列,避免硬编码,再处理原始查询结果:
async findAll() { const toyMetadata = this.toyRepository.metadata; // 获取Toy的非外键数据库列名(排除关联外键字段) const nonForeignKeyColumns = toyMetadata.columns .filter(col => !col.isForeignKey) .map(col => `toy.${col.databaseName}`); // 执行原始查询 const rawResults = await this.toyRepository .createQueryBuilder('toy') .select(nonForeignKeyColumns) .addSelect('userEntity.username', 'user') .where('toy.deleted != :deleted', { deleted: true }) .leftJoin('toy.user', 'userEntity') .getRawMany(); // 将原始结果映射为目标结构 return rawResults.map(result => { const toy = {}; // 映射Toy的属性到实体字段名 toyMetadata.columns .filter(col => !col.isForeignKey) .forEach(col => { toy[col.propertyName] = result[`toy_${col.databaseName}`]; }); // 添加单独的username字段 toy['user'] = result.user; return toy; }); }
关键说明
- 两种方案均无需硬编码Toy的字段,通过TypeORM的实体元数据动态获取列信息
- 若不需要排除外键字段,只需移除代码中
filter(col => !col.isForeignKey)的过滤逻辑即可 - 方案一返回接近实体结构的对象,更贴合ORM使用习惯;方案二直接操作原始查询结果,灵活性更强
内容的提问来源于stack exchange,提问作者sirzento
相关产品推荐
相关产品推荐

