【问题标题】:Mongo create field with merge of 2 arrays of same collection (like Left join in relational)Mongo通过合并同一集合的2个数组创建字段(如关系中的左连接)
【发布时间】:2021-03-10 22:29:18
【问题描述】:

我有一个集合,里面有 2 个数组。一个的道具比另一个少,但两者都由道具“代码”链接。

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

[
  {
    '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 公司,两个数组的元素数量相同,因此第三个数组将是合并,结果将是(只是将道具 TotalDays 添加到数组1):

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

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

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

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

Here is a playgrod with the data

干杯

【问题讨论】:

  • 检查这个playground,将array1 放入array2,对于您的查询操作来说确实很昂贵,我的建议是用您的语言在客户端执行此操作。
  • @turivishal 在您的解决方案中可以正常工作,但只有当两个数组具有相同的代码时才会生效。正如我所说,有时数组 1 会比数组 2 有更多的项目,反之亦然......在这些情况下,数组 3 也需要有这些......
  • 是的,我知道,反之亦然,我只是将它发送给审查,其他人也会有相同的过程,我认为没有其他简单的方法。你真的想要这个在 mongo 查询中吗?因为这就是为什么我建议用你的客户端语言来做这个。
  • 是的,你是对的,在 mongo 查询上做所有事情的成本更高......可能我会在我的 NodeJS 应用程序中做......但我想知道如何在 mogo 中做只是为了研究更多的 mongo函数....查看它们,我发现了一个查找函数,它看起来与关系数据库中的左连接相同...您认为它会起作用吗?喜欢展开两个数组并使用查找?

标签: arrays mongodb mapreduce projection


【解决方案1】:
  • $set检查是否有数组id为null,然后更新为空数组[],以便明确操作
db.collection.aggregate([
  {
    $set: {
      MarketExpertese1: { $ifNull: ["$MarketExpertese1", []] },
      MarketExpertese2: { $ifNull: ["$MarketExpertese2", []] }
    }
  },
  • 准备第三个数组MarketExpertese3,使用数组MarketExpertese2$map迭代循环并与MarketExpertese1$reduce同步以迭代MarketExpertese1的循环并获得匹配的Sector对象并与@987654333合并@的对象使用$mergeObjects
  {
    $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 数组的循环并检查任何状态是新的然后返回否则返回 null,$filter 从数组中删除 null,使用 MarketExpertese3 连接返回数组 $concatArrays
  {
    $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

【讨论】:

  • 几乎可以工作...当array1和2具有相同的itens时工作正常,但是当它们不同时,最终结果会丢失一些道具...这里我有一个真实的例子,关于我的数据Array1 是 MarketExpertises,Array2 是 Statistics.MarketEpertese。结果是 4 个,第一个两个合并确定,最后两个缺少 TotalYears。我想我只需映射最终结果并检查道具 TotalYears 是否存在,如果不存在,则 AddToSet 将修复,对吗? mongoplayground.net/p/hgt2tAYfmwy
  • 这里是正确的游乐场mongoplayground.net/p/RxLlKARXHfE
猜你喜欢
  • 1970-01-01
  • 2019-02-07
  • 1970-01-01
  • 2016-07-20
  • 2021-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-02
相关资源
最近更新 更多