NestJS 10+TypeORM 0.3.17中如何通过嵌套关联属性查询邮编?
解决TypeORM 0.3.x多层关联查询的类型错误问题
背景
使用NestJS 10 + TypeORM 0.3.17,定义了ZipCode、Region、Country关联实体,需要根据邮编(zipCode)和所属国家的countryCode查询ZipCode数据,原写法触发编译错误。
实体定义
ZipCode实体
import { Entity, PrimaryGeneratedColumn, ManyToOne, JoinColumn, Column, Unique, } from 'typeorm'; import { Country } from './country.entity'; import { Region } from './region.entity'; @Entity() @Unique(['zipCode', 'region']) export class ZipCode { @PrimaryGeneratedColumn('uuid') id: string; @Column() zipCode: string; @Column() city: string; @ManyToOne((type) => Region, { onDelete: 'CASCADE', }) @JoinColumn({ name: 'region_id', referencedColumnName: 'id' }) region: Region; }
Region实体
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn, Unique } from 'typeorm'; import { Country } from './country.entity'; @Entity() @Unique(['name', 'country']) export class Region { @PrimaryGeneratedColumn('uuid') id: string; @Column() name: string; @Column() abbrev: string; @ManyToOne((type) => Country) @JoinColumn({ name: 'country_id', referencedColumnName: 'id' }) country: Country; }
原代码问题
原查询存在三个问题:
- 未声明加载
region.country深层关联,TypeORM无法识别嵌套的country.countryCode条件 - 遗漏了
zipCode本身的过滤条件,无法匹配目标邮编 - TypeORM 0.3.x对深层嵌套的
where条件类型检查严格,容易触发类型不兼容错误
正确实现方案
方案1:完善findOne查询
通过声明完整关联链,同时补充过滤条件:
export class ZipCodeRepository extends Repository<ZipCode> { async findByZipCode(zipCode: string, countryCode: string): Promise<ZipCode | null> { return this.findOne({ select: ['zipCode', 'city'], // 必须声明完整的关联层级 relations: ['region', 'region.country'], where: { zipCode, region: { country: { countryCode // 确保Country实体已定义countryCode字段 } } }, }); } }
方案2:使用QueryBuilder(更推荐)
QueryBuilder写法规避类型检查限制,逻辑更清晰:
export class ZipCodeRepository extends Repository<ZipCode> { async findByZipCode(zipCode: string, countryCode: string): Promise<ZipCode | null> { return this.createQueryBuilder('zipCode') .select(['zipCode.zipCode', 'zipCode.city']) // 关联Region和Country表 .innerJoin('zipCode.region', 'region') .innerJoin('region.country', 'country') // 添加过滤条件 .where('zipCode.zipCode = :zipCode', { zipCode }) .andWhere('country.countryCode = :countryCode', { countryCode }) .getOne(); } }
注意:请确认
Country实体中已正确定义countryCode字段,否则查询会执行失败。
内容的提问来源于stack exchange,提问作者Dave
相关产品推荐
相关产品推荐

