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

MongoDB中使用Projection过滤嵌套数组的技术求助

MongoDB聚合:过滤嵌套数组中匹配父文档字段的元素

在MongoDB聚合操作中,完成lookup等步骤后得到如下文档结构:

[
    {
        "_id": ObjectId("6407e265a15acdb137ec651e"),
        "myLocalId": "id1c1",
        "title": "id1c1 title",
        "details": [
            {
                "myLocalId": "id1e2",
                "title": "id2e2 title2",
                "subarray": [
                    {
                        "_id": "id1c1",
                        "displayName": "id1c1 for id2e2"
                    },
                    {
                        "_id": "id1c2",
                        "displayName": "id1c2 for id2e2"
                    }
                ]
            },
            {
                "myLocalId": "id2e3",
                "title": "id2e3 title3",
                "subarray": [
                    {
                        "_id": "id1c1",
                        "displayName": "id1c1 for id2e3"
                    },
                    {
                        "_id": "id2c2",
                        "displayName": "id2c2 for id2e3"
                    }
                ]
            }
        ]
    },
    {
        "_id": ObjectId("6407e26da15acdb137ec651f"),
        "myLocalId": "id2c2",
        "title": "id2c2 title",
        "details": [
            {
                "_id": ObjectId("6407e385a15acdb137ec6526"),
                "myLocalId": "id2e1",
                "title": "id2e1 title",
                "subarray": [
                    {
                        "_id": "id2c2",
                        "displayName": "id2c2 for id2e1"
                    },
                    {
                        "_id": "id2c3",
                        "displayName": "id2c3 for id2e1"
                    }
                ]
            },
            {
                "_id": ObjectId("6407e385a15acdb137ec6526"),
                "myLocalId": "id2e2",
                "title": "id2e1 title",
                "subarray": [
                    {
                        "_id": "id2c2",
                        "displayName": "id2c2 for id2e2"
                    },
                    {
                        "_id": "id2c4",
                        "displayName": "id2c4 for id2e2"
                    }
                ]
            }
        ]
    }
]

需要过滤每个details数组元素下的subarray,仅保留其中_id与父文档myLocalId匹配的元素。尝试使用$project操作符未达到预期效果,期望输出如下结构:

[
    {
        "_id": ObjectId("6407e265a15acdb137ec651e"),
        "myLocalId": "id1c1",
        "title": "id1c1 title",
        "details": [
            {
                "myLocalId": "id1e2",
                "title": "id2e2 title2",
                "subarray": [
                    {
                        "_id": "id1c1",
                        "displayName": "id1c1 for id2e2"
                    }
                ]
            },
            {
                "myLocalId": "id2e3",
                "title": "id2e3 title3",
                "subarray": [
                    {
                        "_id": "id1c1",
                        "displayName": "id1c1 for id2e3"
                    }
                ]
            }
        ]
    },
    {
        "_id": ObjectId("6407e26da15acdb137ec651f"),
        "myLocalId": "id2c2",
        "title": "id2c2 title",
        "details": [
            {
                "_id": ObjectId("6407e385a15acdb137ec6526"),
                "myLocalId": "id2e1",
                "title": "id2e1 title",
                "subarray": [
                    {
                        "_id": "id2c2",
                        "displayName": "id2c2 for id2e1"
                    }
                ]
            },
            {
                "_id": ObjectId("6407e385a15acdb137ec6526"),
                "myLocalId": "id2e2",
                "title": "id2e1 title",
                "subarray": [
                    {
                        "_id": "id2c2",
                        "displayName": "id2c2 for id2e2"
                    }
                ]
            }
        ]
    }
]

解决方案

使用$map遍历外层details数组,结合$filter筛选每个subarray中符合条件的元素,聚合管道如下:

db.collection.aggregate([
  {
    $addFields: {
      "details": {
        $map: {
          input: "$details",
          as: "detail",
          in: {
            // 保留原detail的所有字段,替换subarray为过滤后的结果
            ..."$$detail",
            "subarray": {
              $filter: {
                input: "$$detail.subarray",
                as: "item",
                cond: { $eq: ["$$item._id", "$myLocalId"] }
              }
            }
          }
        }
      }
    }
  }
])

说明:

  • $map:遍历details数组,对每个元素进行自定义处理
  • $filter:在每个detail的subarray中,筛选出_id等于父文档myLocalId的元素
  • ...$$detail:保留detail原有全部字段(需MongoDB 4.2及以上版本支持),若版本较低,可显式列出需要保留的字段,例如:
    in: {
      "_id": "$$detail._id",
      "myLocalId": "$$detail.myLocalId",
      "title": "$$detail.title",
      "subarray": { /* 过滤逻辑 */ }
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 18:52:06