Mongo 聚合平面嵌套数组

时间:2021-02-05 01:13:44

标签: mongodb mongodb-query

我在 Mongo 中有这样的结构:

public class Games : BaseCommandModule
{
    [Command("rps")]
    public async Task ReactionCommand(CommandContext ctx, DiscordMember member)
    {
        var emoji = DiscordEmoji.FromName(ctx.Client, ":scissors:");
        var challenger = ctx.Member;
        var opponent = member;
        var message = await ctx.RespondAsync($"{opponent.Mention}, react with {emoji} if you'd like to play Rock Paper Scissors with {challenger.DisplayName}?");
        await message.CreateReactionAsync(emoji);
        var result = await message.WaitForReactionAsync(opponent, emoji);
        if (!result.TimedOut)
        {
            var message2 = await ctx.RespondAsync($"{opponent.Mention}, react with your choice.");
            await message2.CreateReactionAsync(DiscordEmoji.FromName(ctx.Client, ":rock:"));
            await message2.CreateReactionAsync(DiscordEmoji.FromName(ctx.Client, ":scissors:"));
            await message2.CreateReactionAsync(DiscordEmoji.FromName(ctx.Client, ":roll_of_paper:"));
        }
    }

}

我需要将所有“Billings”平铺到 root,但其中一些位于第一级数组中,而其他则向下 2 级。

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

我怎样才能把所有东西都压平?只需放松 2 次和 MergeArray ?要将 ID 推送到 Billings,我应该使用 MAP 吗?

在这个例子中,结果是:

[
  {
    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
          }
        ]
      }
    ]
  }
]

这是一个Mongo Playground

干杯

2 个答案:

答案 0 :(得分:3)

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

  • $project 将顶级 Billings$extras 数组组合
  • 展开 ExtrasBillings,使每个文档只包含一个
  • ProjectIdExtraId 添加到计费对象
  • 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"
  }}
])

Playground

答案 1 :(得分:0)

你可以试试这个聚合查询:

db.collection.aggregate([
  {
    "$unwind": "$Extras"
  },
  {
    "$addFields": {
      "Extras.Billings.ExtraId": "$Extras.ExtraId"
    }
  },
  {
    "$project": {
      "ProjectId": "$ProjectId",
      "Billings": {
        "$concatArrays": [
          "$Billings",
          "$Extras.Billings"
        ]
      }
    }
  },
  {
    "$unwind": "$Billings"
  },
  {
    "$project": {
      "ProjectId": "$ProjectId",
      "FieldA": "$Billings.FieldA",
      "ExtraId": "$Billings.ExtraId"
    }
  },
  {
    "$group": {
      "_id": {
        "id": "$_id",
        "FieldA": "$FieldA",
        "ProjectId": "$ProjectId",
        "ExtraId": "$ExtraId"
      }
    }
  },
  {
    "$project": {
      "_id": 0,
      "FieldA": "$_id.FieldA",
      "ProjectId": "$_id.ProjectId",
      "ExtraIs": "$_id.ExtraId"
    }
  },
  {
    "$sort": {
      "ProjectId": 1,
      "FieldA": 1
    }
  }
])

在线试用:mongoplayground.net/p/DZAIfDY5x7L