首页 > 解决方案 > Mongodb - 基于特定属性合并嵌套子文档数组

问题描述

我已经建立了一个返回这些数据的聚合:

 [
      {
        "users": [
          {
            _id: 1,
            name: "John",
            age: 31
          },
          {
            _id: 2,
            name: "Jane",
            age: 26
          }
        ],
        "teams": [
          {
            id: 1,
            name: "Team 1",
            color: "yellow"
          },
          {
            id: 2,
            name: "Team 2",
            color: "red"
          }
        ],
        "moreTeams": [
          {
            id: 1,
            name: "Team 1 - More",
          },
          {
            id: 2,
            name: "Team 2 - More",
          },
          {
            id: 3,
            name: "Team 3 - More",
            extra: "extra"
          }
        ]
      }
    ]

如何将“团队”分组并moreTeams放入同一个数组(基于 id),保留所有属性并最终覆盖它们具有相同名称的位置?

这是我想要的结果:

 [
          {
            "users": [
              {
                _id: 1,
                name: "John",
                age: 31
              },
              {
                _id: 2,
                name: "Jane",
                age: 26
              }
            ],
            "groupedTeams": [
              {
                id: 1,
                name: "Team 1 - More",
                color: "yellow"
              },
              {
                id: 2,
                name: "Team 2 - More",
                color: "red"
              },
              {
                id: 3,
                name: "Team 3 - More",
                extra: "extra"
              }
            ]
          }
        ]

我试过使用 $unwind 和 $group 没有成功:(

游乐场示例:https ://mongoplayground.net/p/yZY8oQ9r-N1

标签: mongodbaggregation-framework

解决方案


  • $mapmoreTeams迭代数组的循环
  • $filter迭代数组循环teams并过滤匹配对象id
  • $arrayElemAt从上面的过滤器中获取第一个元素对象
  • $mergeObjects合并上面的对象arrayElemAt和当前对象
db.collection.aggregate([
  {
    $addFields: {
      moreTeams: {
        $map: {
          input: "$moreTeams",
          as: "m",
          in: {
            $mergeObjects: [
              {
                $arrayElemAt: [
                  {
                    $filter: {
                      input: "$teams",
                      cond: { $eq: ["$$m.id", "$$this.id"] }
                    }
                  },
                  0
                ]
              },
              "$$m"
            ]
          }
        }
      }
    }
  },

现在我们已经合并moreTeams了,teams但我们也必须teams合并moreTeams

  • $project,$filter迭代数组循环teams并匹配条件(如果id不在)moreTeams
  • $concatArrays连接moreTeams及以上过滤后的数组moreTeams
  {
    $project: {
      users: 1,
      moreTeams: {
        $concatArrays: [
          "$moreTeams",
          {
            $filter: {
              input: "$teams",
              cond: { $not: { $in: ["$$this.id", "$moreTeams.id"] } }
            }
          }
        ]
      }
    }
  }
])

操场


推荐阅读