如何修改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
相关产品推荐
相关产品推荐

