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

如何在Nest JS中实现动态筛选?商用应用多字段需求

动态多字段筛选实现方案(基于NestJS + TypeORM)

你的现有代码硬编码了筛选字段和查询条件,新增字段就得修改代码,完全没法适配动态多字段的需求,而且where数组的写法会产生OR逻辑,大概率不是你要的筛选效果(应该是价格范围和其他字段的AND组合)。下面是重构后的实现方案:

重构Service层代码

用TypeORM的QueryBuilder来动态构建查询条件,不用逐一指定字段:

public async filtering(filterParams: any) {
  // 创建查询构建器,指定表别名
  const queryBuilder = this.announsRepo.createQueryBuilder('announ');
  // 分离价格范围参数和其他筛选字段
  const { pricee, priceEnd, ...otherFilters } = filterParams;

  // 处理价格范围的三种情况
  if (pricee && priceEnd) {
    queryBuilder.andWhere('announ.price BETWEEN :pricee AND :priceEnd', { pricee, priceEnd });
  } else if (pricee) {
    queryBuilder.andWhere('announ.price >= :pricee', { pricee });
  } else if (priceEnd) {
    queryBuilder.andWhere('announ.price <= :priceEnd', { priceEnd });
  }

  // 动态遍历所有其他筛选字段,自动添加查询条件
  Object.entries(otherFilters).forEach(([key, value]) => {
    // 过滤空值,避免无效查询
    if (value !== undefined && value !== null && value !== '') {
      // 默认精确匹配,如需模糊搜索可改为 LIKE :${key} 并设置value为 `%${value}%`
      queryBuilder.andWhere(`announ.${key} = :${key}`, { [key]: value });
    }
  });

  // 执行查询获取结果
  const result = await queryBuilder.getMany();
  return { filterParams, result };
}

优化建议

1. 用DTO替代any,增强类型安全

创建filter.dto.ts定义筛选参数的类型,避免any带来的类型风险:

export class FilterDto {
  pricee?: number;
  priceEnd?: number;
  place?: string;
  used?: boolean;
  currency?: string;
  publishedAt?: Date;
  field1?: string;
  field2?: string;
  field3?: string;
  // 后续新增字段直接在这里添加即可
}

然后修改Controller的参数类型:

@ApiOperation({ summary: "筛选" })
@Get('getFiltered')
public async filtering(
  @Query() filterParams: FilterDto
) {
  return this.announsService.filtering(filterParams);
}

2. 扩展字段匹配逻辑

如果某些字段需要特殊处理(比如日期范围、模糊搜索),可以在遍历的时候加判断:

Object.entries(otherFilters).forEach(([key, value]) => {
  if (!value) return;
  switch(key) {
    case 'publishedAt':
      // 比如只筛选发布日期早于指定时间的内容
      queryBuilder.andWhere('announ.publishedAt <= :publishedAt', { publishedAt: value });
      break;
    case 'field1':
      // 模糊匹配示例
      queryBuilder.andWhere('announ.field1 LIKE :field1', { field1: `%${value}%` });
      break;
    default:
      // 默认精确匹配
      queryBuilder.andWhere(`announ.${key} = :${key}`, { [key]: value });
  }
});

3. 添加分页支持

如果数据量较大,建议加上分页参数:

public async filtering(filterParams: any) {
  const queryBuilder = this.announsRepo.createQueryBuilder('announ');
  // 提取分页参数,默认第一页每页10条
  const { page = 1, limit = 10, pricee, priceEnd, ...otherFilters } = filterParams;

  // ...价格范围和其他字段处理逻辑

  // 添加分页
  queryBuilder.skip((page - 1) * limit).take(limit);

  const result = await queryBuilder.getMany();
  // 可以额外返回总条数
  const total = await queryBuilder.getCount();
  return { filterParams, result, total };
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 08:50:26