Mongo 通过合并同一集合的 2 个数组创建字段(如关系中的左连接)

Mongo create field with merge of 2 arrays of same collection (like Left join in relational)

我有一个集合,里面有 2 个数组。一个的道具比另一个少,但两者都由道具 'Code'.

链接

我想投射第三个数组,它是两者的合并,但它们必须不同。一个例子:

[
  {
    'PartnerName': "Company A - Both Complete Equal",
    'MarketExpertese1': [
      { 'Sector': { 'Code': 1, 'Label': 'Sector 1' } },
      { 'Sector': { 'Code': 2, 'Label': 'Sector 2' } }
    ],
    'MarketExpertese2': [
      { 'Sector': { 'Code': 1, 'TotalDays': 1 } },
      { 'Sector': { 'Code': 2, 'TotalDays': 1 } }
    ]
  },
    {
    'PartnerName': "Company B - 1 has more",
    'MarketExpertese1': [
      { 'Sector': { 'Code': 1, 'Label': 'Sector 1' } },
      { 'Sector': { 'Code': 2, 'Label': 'Sector 2' } },
      { 'Sector': { 'Code': 3, 'Label': 'Sector 3' } }
    ],
    'MarketExpertese2': [
      { 'Sector': { 'Code': 1, 'TotalDays': 1 } },
      { 'Sector': { 'Code': 2, 'TotalDays': 1 } }
    ]
  },
  {
    'PartnerName': "Company C - 2 has more",
    'MarketExpertese1': [
      { 'Sector': { 'Code': 1, 'Label': 'Sector 1' } },
      { 'Sector': { 'Code': 2, 'Label': 'Sector 2' } }
    ],
    'MarketExpertese2': [
      { 'Sector': { 'Code': 1, 'TotalDays': 1 } },
      { 'Sector': { 'Code': 2, 'TotalDays': 1 } },
      { 'Sector': { 'Code': 3, 'TotalDays': 1 } }
    ]
  },
  {
    'PartnerName': "Company D - 1 has - 2 Null",
    'MarketExpertese1': [
      { 'Sector': { 'Code': 1, 'Label': 'Sector 1' } }
    ],
    'MarketExpertese2': null
  },
  {
    'PartnerName': "Company E - 1 null - 2 has",
    'MarketExpertese1': null,
    'MarketExpertese2': [
      { 'Sector': { 'Code': 1, 'TotalDays': 1 } }
    ]
  }
]

在公司 A 中,两个数组具有相同数量的 itens,因此第三个数组将是合并,结果将是(刚刚将道具 TotalDays 添加到数组 1):

'MarketExpertese3': [
      { 'Sector': { 'Code': 1, 'Label': 'Sector 1', 'TotalDays': 10 } },
      { 'Sector': { 'Code': 2, 'Label': 'Sector 2', 'TotalDays': 20 } }
    ]

在此示例中,两个数组具有相同的长度和相同的代码,但有时它们不同。有时一个是空的,另一个不是,有时是空的,等等...

有时我必须添加 TotalDays:0 当 array1 有更多的 itens 数组 2。有时我必须将 prop 从数组 1 填充到数组 2。

环顾四周 我迷路了,我不知道我是否需要 unwind/group/map 或 unwind/reduce/group/map... 当我需要验证两者的道具代码以检查是否我需要获取数组 1 并合并到 2 中,反之亦然

Here is a playgrod with the data

干杯

  • $set检查是否有数组id为null然后更新为空数组[],用于清除操作
db.collection.aggregate([
  {
    $set: {
      MarketExpertese1: { $ifNull: ["$MarketExpertese1", []] },
      MarketExpertese2: { $ifNull: ["$MarketExpertese2", []] }
    }
  },
  • 准备第三个数组 MarketExpertese3,使用数组 MarketExpertese2$map 迭代循环并与 MarketExpertese1$reduce 同步以迭代 [=17] 的循环=] 并获得匹配的 Sector 对象并使用 $mergeObjects
  • MarketExpertese2 的对象合并
  {
    $addFields: {
      MarketExpertese3: {
        $map: {
          input: "$MarketExpertese2",
          as: "m",
          in: {
            Sector: {
              $mergeObjects: [
                "$$m.Sector",
                {
                  $reduce: {
                    input: "$MarketExpertese1",
                    initialValue: {},
                    in: {
                      $cond: [
                        { $eq: ["$$m.Sector.Code", "$$this.Sector.Code"] },
                        "$$this.Sector",
                        "$$value"
                      ]
                    }
                  }
                }
              ]
            }
          }
        }
      }
    }
  },
  • 现在我们需要将 MarketExpertese1 数组同步到 MarketExpertese3 新准备的数组,
  • $map 迭代 MarketExpertese1 数组的循环并检查任何状态是新的然后 return 否则 return null,$filter 从中删除 null数组,使用 $concatArrays
  • MarketExpertese3 连接 return 数组
  {
    $addFields: {
      MarketExpertese3: {
        $concatArrays: [
          "$MarketExpertese3",
          {
            $filter: {
              input: {
                $map: {
                  input: "$MarketExpertese1",
                  as: "m",
                  in: {
                    $cond: [
                      {
                        $eq: [
                          {
                            $filter: {
                              input: "$MarketExpertese2",
                              cond: { $eq: ["$$this.Sector.Code", "$$m.Sector.Code"] }
                            }
                          },
                          []
                        ]
                      },
                      "$$m",
                      "$$REMOVE"
                    ]
                  }
                }
              },
              cond: { $ne: ["$$this", null] }
            }
          }
        ]
      }
    }
  }
])

Playground