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

如何优化Angular+NestJS+GraphQL+MongoDB多字段过滤函数?

多字段过滤逻辑优化方案(Angular/NestJS/GraphQL/MongoDB)

我当前使用Angular、NestJS、GraphQL和MongoDB技术栈开发,现有一个多字段数据过滤模态组件,原有的过滤代码存在大量冗余条件判断,希望优化为更整洁的实现。

原冗余代码示例

let matchingValue: any;
let matchingValuePipeline: any;
// const { bySn, byBank, byClient, byModel, byRegion, bySite, byTerminalId } =
//   search;
for (let item in search) {
  if (search[item] === '') {
    matchingValue = { inUse: true };
    matchingValuePipeline = { bindedSuperAdmin: name };
  }
}
//-----------------------------
if (search.byBank) {
  matchingValuePipeline = { bindedBanque: search.byBank };
}
if (search.byBank && search.byClient) {
  matchingValuePipeline = {
    bindedBanque: search.byBank,
    bindedClient: search.byClient,
  };
}
if (search.byBank && search.byClient && search.bySite) {
  matchingValuePipeline = {
    bindedBanque: search.byBank,
    bindedClient: search.byClient,
    nameUser: search.bySite,
  };
}
if (search.byBank && search.byClient && search.bySite && search.byModel) {
  matchingValuePipeline = {
    bindedBanque: search.byBank,
    bindedClient: search.byClient,
    nameUser: search.bySite,
  };
  matchingValue = { inUse: true, model: search.byModel };
}
if (
  search.byBank &&
  search.byClient &&
  search.bySite &&
  search.byModel &&
  search.byRegion
) {
  matchingValuePipeline = {
    bindedBanque: search.byBank,
    bindedClient: search.byClient,
    nameUser: search.bySite,
    region: search.byRegion,
  };
  matchingValue = { inUse: true, model: search.byModel };
}
if (
  search.byBank &&
  search.byClient &&
  search.bySite &&
  search.byModel &&
  search.byRegion &&
  search.bySn
) {
  matchingValuePipeline = {
    bindedBanque: search.byBank,
    bindedClient: search.byClient,
    nameUser: search.bySite,
    region: search.byRegion,
  };
  matchingValue = { inUse: true, model: search.byModel, sn: search.bySn };
}
if (
  search.byBank &&
  search.byClient &&
  search.bySite &&
  search.byModel &&
  search.byRegion &&
  search.bySn &&
  search.byTerminalId
) {
  matchingValuePipeline = {
    bindedBanque: search.byBank,
    bindedClient: search.byClient,
    nameUser: search.bySite,
    region: search.byRegion,
  };
  matchingValue = {
    inUse: true,
    model: search.byModel,
    sn: search.bySn,
    terminalId: search.byTerminalId,
  };
}

if (search.byClient) {
  matchingValuePipeline = { bindedClient: search.byClient };
}
if (search.bySite) {
  matchingValuePipeline = { nameUser: search.bySite };
}
if (search.byRegion) {
  matchingValuePipeline = { region: search.byRegion };
}
if (search.bySn) {
  matchingValue = { sn: search.bySn };
}
if (search.byModel) {
  matchingValue = { model: search.byModel };
}
if (search.byTerminalId) {
  matchingValue = { terminalId: search.byTerminalId };
}

//--------------------------------------
// for testing purpose
console.log('matchingValue', matchingValue);
console.log('matchingValuePipeline', matchingValuePipeline);
console.log('search', search);

let filter;
if (role === ROLEV1.MS_TECH_SOFT) {
  filter = await this.modelTpe.aggregate([
    {
      $match: matchingValue,
    },
    {
      $lookup: {
        from: 'profiles',
        localField: 'merchantName',
        foreignField: 'nameUser',
        as: 'listTpe',
        pipeline: [
          {
            $match: matchingValuePipeline,
          },
        ],
      },
    },

对应的SearchMethods DTO:

@InputType()
export class SearchMethods {
  @Field({ nullable: true })
  bindedBanque?: string;
  @Field({ nullable: true })
  bindedClient?: string;
  @Field({ nullable: true })
  nameUser?: string;
  @Field({ nullable: true })
  region?: string;
  @Field({ nullable: true })
  model?: string;
  @Field({ nullable: true })
  sn: string;
  @Field({ nullable: true })
  terminalId?: string;
}

优化后的实现方案

核心逻辑代码

// 定义前端搜索参数到MongoDB字段的映射关系
const pipelineFieldMap = {
  byBank: 'bindedBanque',
  byClient: 'bindedClient',
  bySite: 'nameUser',
  byRegion: 'region',
};

const valueFieldMap = {
  bySn: 'sn',
  byModel: 'model',
  byTerminalId: 'terminalId',
};

// 初始化匹配对象,设置默认条件
const matchingValue: any = { inUse: true };
const matchingValuePipeline: any = { bindedSuperAdmin: name };

// 处理空值情况:如果有任何搜索字段为空,保留默认条件(可根据需求调整)
const hasEmptyField = Object.values(search).some(val => val === '');
if (!hasEmptyField) {
  // 动态构建matchingValuePipeline
  Object.entries(pipelineFieldMap).forEach(([searchKey, dbField]) => {
    if (search[searchKey]) {
      matchingValuePipeline[dbField] = search[searchKey];
    }
  });

  // 动态构建matchingValue
  Object.entries(valueFieldMap).forEach(([searchKey, dbField]) => {
    if (search[searchKey]) {
      matchingValue[dbField] = search[searchKey];
    }
  });
}

// 测试输出
console.log('matchingValue', matchingValue);
console.log('matchingValuePipeline', matchingValuePipeline);
console.log('search', search);

// 集成到聚合查询
let filter;
if (role === ROLEV1.MS_TECH_SOFT) {
  filter = await this.modelTpe.aggregate([
    { $match: matchingValue },
    {
      $lookup: {
        from: 'profiles',
        localField: 'merchantName',
        foreignField: 'nameUser',
        as: 'listTpe',
        pipeline: [{ $match: matchingValuePipeline }],
      },
    },
    // 其他聚合阶段...
  ]);
}

优化点说明

  • 字段映射配置:用pipelineFieldMap和valueFieldMap统一管理前端参数与数据库字段的对应关系,后续新增/修改字段只需调整映射表,无需修改业务逻辑
  • 动态条件构建:通过遍历映射表自动添加非空条件,彻底消除多层嵌套的if判断
  • 默认条件统一处理:初始化时直接设置inUse: true和bindedSuperAdmin的默认值,空值场景单独判断后保留默认逻辑
  • 代码简洁可维护:原100+行的条件判断压缩到30行以内,逻辑清晰,降低后续维护成本

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 21:35:59