You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于关联值过滤NestJS Repository的查询结果?

解决NestJS+TypeORM中获取未关联Warehouse的Address数据问题

先修正实体定义的错误

你的Address实体中warehouse字段的类型定义有误,应该关联到Warehouse实体而非string | null,TypeORM需要正确的实体类型来处理关联关系:

@Entity()
export class Address {
    [key: string]: string | string[] | number | Record<string, unknown> | Date;
    @PrimaryGeneratedColumn({
        type: "bigint",
        name: "address_id",
    })
    id: string;

    @Column({
        nullable: true,
    })
    customerId?: string;

    @Field()
    @OneToOne(() => Warehouse, (warehouse: Warehouse) => warehouse.address, { nullable: true })
    // 修正类型为Warehouse | null
    warehouse?: Warehouse | null;
}

使用Repository实现过滤逻辑

由于外键字段address_id存在于Warehouse表中(因为Warehouse加了@JoinColumn),直接通过warehouse: null或IsNull()过滤会失效,需要通过子查询检查是否存在关联的Warehouse记录来实现。

使用TypeORM的Not和Exists操作符,结合Repository的find方法完成查询:

import { Not, Exists, Repository } from 'typeorm';
import { Injectable } from '@nestjs/common';
import { Address } from './entities/address.entity';

@Injectable()
export class AddressesService {
  constructor(
    @InjectRepository(Address)
    private addressRepository: Repository<Address>,
  ) {}

  findAllAddresses() {
    return this.addressRepository.find({
      where: {
        id: Not(Exists(
          this.addressRepository.createQueryBuilder('warehouse')
            .select('1')
            .where('warehouse.address_id = address.address_id')
        ))
      },
      // 无需关联warehouse,我们要找的是未关联的地址,加载关联只会增加不必要开销
    });
  }
}

逻辑说明

  • 通过Exists子查询检查当前Address的id是否在Warehouse表的address_id字段中存在
  • 用Not取反,得到所有不存在对应Warehouse记录的Address数据

为什么之前的方法失效?

  • 直接写warehouse: null时,TypeORM无法正确解析关联字段的空值过滤,因为Address表本身没有存储Warehouse的外键,外键在Warehouse表中
  • 使用IsNull()时,TypeORM会尝试在Address表中找对应的字段,但该字段不存在,因此抛出This relation isn't supported by given find operator错误

内容的提问来源于stack exchange,提问作者m3.b

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 01:15:51