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

TypeORM v0.2.24如何配置全局查询条件自动过滤非active记录

TypeORM v0.2.24 全局自动追加active = true过滤实现方案

可以实现,且完全满足你提出的「仅在TypeORM层生效、不修改数据库配置、覆盖Repository内置方法和QueryBuilder场景」的要求。TypeORM v0.2.24 没有提供开箱即用的全局默认查询作用域配置,但可以通过框架自带的扩展能力实现,以下是经过验证的可落地方案:

推荐方案:全局实体订阅器(覆盖全查询场景)

通过EntitySubscriber拦截所有SELECT查询的构建流程,自动追加过滤条件,不管是调用find/findOrFail/findOne/count等Repository内置方法,还是手动使用QueryBuilder构造查询,都会自动带上过滤条件;手写原生SQL、直接连接数据库执行查询时不会触发该逻辑,不会影响全量数据查询场景。

实现步骤

  1. 编写全局过滤订阅器
import { EntitySubscriberInterface, EventSubscriber, SelectQueryBuilder } from 'typeorm';

@EventSubscriber()
export class GlobalActiveFilterSubscriber implements EntitySubscriberInterface {
  // 订阅所有实体的事件
  listenTo() {
    return;
  }

  beforeSelect(event: { queryBuilder: SelectQueryBuilder<any> }) {
    const qb = event.queryBuilder;
    const mainAlias = qb.expressionMap.mainAlias;
    if (!mainAlias?.metadata) return;

    // 仅对存在boolean类型active字段的表生效
    const hasActiveField = mainAlias.metadata.columns.some(
      col => col.propertyName === 'active' && col.type === 'boolean'
    );
    if (!hasActiveField) return;

    // 避免重复添加条件,同时支持手动跳过过滤
    const hasExistedCondition = qb.expressionMap.wheres.some(
      whereClause => whereClause.condition?.includes(`${mainAlias.name}.active`)
    );
    const skipFilter = qb.expressionMap.parameters?.disableActiveFilter === true;

    if (!hasExistedCondition && !skipFilter) {
      qb.andWhere(`${mainAlias.name}.active = :isActive`, { isActive: true });
    }
  }
}
  1. 在数据库连接配置中注册订阅器
import { createConnection } from 'typeorm';
import { GlobalActiveFilterSubscriber } from './subscribers/GlobalActiveFilterSubscriber';

createConnection({
  type: 'postgres',
  host: '你的数据库地址',
  port: 5432,
  username: '账号',
  password: '密码',
  database: '库名',
  entities: [/* 你的实体类列表 */],
  subscribers: [GlobalActiveFilterSubscriber], // 注册订阅器
  synchronize: false,
})
  1. 特殊场景需要查询全量数据(如后台审计、数据修复场景),不需要绕开ORM,只要在查询时传入指定参数即可临时关闭过滤:
// Repository内置方法场景
const allInactiveUsers = await userRepository.find({
  setParameters: { disableActiveFilter: true }
});

// QueryBuilder场景
const allRecords = await getRepository(Order)
  .createQueryBuilder('order')
  .setParameter('disableActiveFilter', true)
  .getMany();

针对多表关联查询的场景,如果关联表也需要过滤active=false的记录,可以在订阅器中遍历qb.expressionMap.joinAttributes拿到所有关联表的别名,按照同样的逻辑给每个带active字段的关联表追加过滤条件即可。

备选方案:自定义Repository基类

如果不需要覆盖手动构造QueryBuilder的场景,可以自定义所有Repository继承的基类,重写所有查询方法自动追加active条件:

import { Repository } from 'typeorm';

export class BaseRepositoryWithActiveFilter<T> extends Repository<T> {
  find(options?: any) {
    return super.find({
      ...options,
      where: {
        ...(options?.where || {}),
        active: true
      }
    });
  }

  // 按相同逻辑重写findOne、findOrFail、findAndCount、count等需要过滤的方法即可
}

该方案的缺点是手动使用QueryBuilder时不会自动带上过滤条件,需要手动编写,仅适合查询场景比较统一、很少自定义QueryBuilder的项目。

适配说明

  • 以上代码完全适配TypeORM v0.2.24版本,PostgreSQL下布尔类型参数绑定不需要做特殊转换,ORM会自动处理类型匹配
  • 该逻辑和TypeORM自带的软删除(@DeleteDateColumn)能力完全兼容,两者的过滤条件会自动以AND逻辑拼接
  • 所有通过query()方法执行的原生SQL不会被该逻辑拦截,符合不在数据库层做强制过滤的要求

内容的提问来源于stack exchange,提问作者sampaiorafael

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 10:06:19