首页 > 解决方案 > Mongo 聚合平面嵌套数组

问题描述

我在 Mongo 有这个结构:

[
  {
    ProjectId: 111,
    Billings: [
      {
        FieldA: 1
      },
      {
        FieldA: 2
      }
    ],
    Extras: [
      {
        ExtraId: "E_111_01",
        Billings: [
          {
            FieldA: 3
          },
          {
            FieldA: 4
          }
        ]
      },
      {
        ExtraId: "E_111_02",
        Billings: [
          {
            FieldA: 5
          },
          {
            FieldA: 6
          }
        ]
      }
    ]
  },
  {
    ProjectId: 222,
    Billings: [],
    Extras: [
      {
        ExtraId: "E_222_01",
        Billings: [
          {
            FieldA: 7
          },
          {
            FieldA: 8
          }
        ]
      }
    ]
  }
]

我需要将所有 'Billings' 归为 root,但其中一些位于第一级数组中,而另一些位于 2 级以下。

并且该过程应该向“Billing”添加 2 个道具,即它来自的项目 ID,如果它是 Extra,则“Billings”应该具有项目 ID 和 Extra ID。

我怎样才能把所有东西都平铺成根?只是 Unwind 2 次和 MergeArray ?将 ID 推送到比林斯,我应该使用 MAP 吗?

在此示例中,结果将是:

[
    {
        ProjectId: 111,
        FieldA: 1
    },
    {
        ProjectId: 111,
        FieldA: 2
    }
    {
        ProjectId: 111,
        ExtraId: "E_111_01",
        FieldA: 3
    },
    {
        ProjectId: 111,
        ExtraId: "E_111_01",
        FieldA: 4
    }
    {
        ProjectId: 111,
        ExtraId: "E_111_01",
        FieldA: 5
    },
    { 
        ProjectId: 111,
        ExtraId: "E_111_01",
        FieldA: 6
    }
    {
        ProjectId: 222,
        ExtraId: "E_222_01",
        FieldA: 7
    },
    {
        ProjectId: 222,
        ExtraId: "E_222_01",
        FieldA: 8
    }
]

这是一个Mongo游乐场

干杯

标签: mongodbmongodb-query

解决方案


假设FieldA在您的示例中是一个可能是多个字段或不同名称的占位符,您可能

  • $project 将顶层Billings$extras数组结合起来
  • 展开ExtrasBillings因此每个文档只包含一个
  • ProjectId将和添加ExtraId到计费对象
  • Billings文档提升为根

这将保留每个Billings文档中的所有字段,并且不需要您提前知道字段名称。

db.collection.aggregate([
  {"$project": {
      _id: 0,
      ProjectId: 1,
      Extras: {
        $concatArrays: [
          [{ Billings: "$Billings" }],
          "$Extras"
        ]
      }
  }},
  {$unwind: "$Extras"},
  {$unwind: "$Extras.Billings"},
  {$addFields: {
      "Extras.Billings.ExtraId": "$Extras.ExtraId",
      "Extras.Billings.ProjectId": "$ProjectId"
   }},
  {$replaceRoot: {
      newRoot: "$Extras.Billings"
  }}
])

操场


推荐阅读