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

如何修改MongoDB双层嵌套数组中的指定对象字段

如何在NestJS中筛选并更新MongoDB嵌套数组中的对象字段

一、修正聚合管道以筛选嵌套数组

你当前的聚合管道未先筛选目标build,导致内层artifacts的筛选逻辑失效。要同时筛选外层builds和内层artifacts,需结合$filter和$map操作实现:

async getBuildItemArtifacts(id: string, buildItemId: string, artifactId: string) {
  const buildPlanCondition = isMongoId(id)
    ? { _id: new Types.ObjectId(id) }
    : { key: id };

  const matchStage: PipelineStage.Match = { $match: buildPlanCondition };
  const filterStages: PipelineStage[] = [
    // 第一步:筛选出指定的build对象
    {
      $project: {
        builds: {
          $filter: {
            input: '$builds',
            as: 'build',
            cond: { $eq: ['$$build._id', new Types.ObjectId(buildItemId)] }
          }
        }
      }
    },
    // 第二步:对筛选后的build的artifacts进行二次筛选
    {
      $addFields: {
        builds: {
          $map: {
            input: '$builds',
            as: 'build',
            in: {
              ...'$$build',
              artifacts: {
                $filter: {
                  input: '$$build.artifacts',
                  as: 'artifact',
                  cond: { $eq: ['$$artifact._id', new Types.ObjectId(artifactId)] }
                }
              }
            }
          }
        }
      }
    },
    // 可选:将build对象提为根文档,简化返回结果结构
    { $unwind: '$builds' },
    { $replaceRoot: { newRoot: '$builds' } }
  ];

  const result = await this.builds
    .aggregate<Partial<Build>>([matchStage, ...filterStages])
    .first();

  if (!result || _.isEmpty(result.artifacts)) {
    throw new ApiError(HttpStatus.NOT_FOUND, 'No data found');
  }

  return result;
}

二、直接更新嵌套数组字段的高效方案

你的核心需求是修改minioPath字段,用聚合管道查询后再更新属于两次数据库操作,效率较低。推荐使用MongoDB的updateOne结合数组过滤器(arrayFilters),直接在数据库层面完成更新:

async updateArtifactMinioPath(
  planId: string,
  buildId: string,
  artifactId: string,
  newMinioPath: string
) {
  const planCondition = isMongoId(planId)
    ? { _id: new Types.ObjectId(planId) }
    : { key: planId };

  const updateResult = await this.builds.updateOne(
    planCondition,
    // 指定要更新的嵌套字段路径
    { $set: { 'builds.$[build].artifacts.$[artifact].minioPath': newMinioPath } },
    // 定义数组过滤器,匹配目标build和artifact
    {
      arrayFilters: [
        { 'build._id': new Types.ObjectId(buildId) },
        { 'artifact._id': new Types.ObjectId(artifactId) }
      ]
    }
  );

  if (updateResult.matchedCount === 0) {
    throw new ApiError(HttpStatus.NOT_FOUND, 'Plan not found');
  }
  if (updateResult.modifiedCount === 0) {
    throw new ApiError(HttpStatus.NOT_FOUND, 'Target build or artifact not found');
  }

  return { success: true, message: 'Artifact path updated' };
}

关键说明

  • arrayFilters用于指定嵌套数组的匹配条件,$[build]和$[artifact]是占位符,对应过滤器中的别名,能精准定位到深层嵌套的目标对象。
  • 聚合管道更适合复杂查询场景,而更新操作直接用updateOne+数组过滤器是最优解,避免额外的查询开销。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 23:50:06