【问题标题】:How to unwind nested object arrays in mongodb aggregation?如何在 mongodb 聚合中展开嵌套对象数组?
【发布时间】:2021-07-20 11:44:33
【问题描述】:

我有一些包含另一个数组的对象数组的数据。我正在尝试展开 courses 数组,然后展开 requirements 数组以匹配主题,然后将所有内容组合在一起。

到目前为止,我可以很好地使用 courses 数组。但是我无法为第二个数组requirements做同样的事情。

[
  {
    "_id": 1,
    "name": "provider name",
    "courses": [
      {
        "_id": 1,
        "name": "course name",
        "requirements": [
          {
            "subjects": [
              "SubjectA::B",
              "SubjectB::B",
              "SubjectC::B"
            ]
          },
          {
            "subjects": [
              "SubjectA::B",
              "SubjectB::B",
              "SubjectC::B"
            ]
          }
        ]
      }
    ]
  }
]

首先我展开两个数组

  {
    $unwind: {
      path: '$courses',
      preserveNullAndEmptyArrays: true
    }
  },
  {
    $unwind: {
      path: '$courses.requirements',
      preserveNullAndEmptyArrays: true
    }
  },

我如何对第一个数组进行分组

  {
    $group: {
      _id: '$_id',
      root: { $mergeObjects: '$$ROOT' },
      courses: { $push: '$courses' }
    }
  },
  {
    $replaceWith: {
      $mergeObjects: ['$root', '$$ROOT'],
    }
  },
  {
    $project: { root: 0 }
  },

预期输出

[
  {
    "_id": 1,
    "name": "provider name",
    "courses": [
      {
        "_id": 1,
        "name": "course name",
        "requirements": [
          {
            "subjects": [
              "SubjectA::B",
              "SubjectB::B",
              "SubjectC::B"
            ]
          },
          {
            "subjects": [
              "SubjectA::B",
              "SubjectB::B",
              "SubjectC::B"
            ]
          }
        ]
      }
    ]
  }
]

但我明白了

[
  {
    "_id": 1,
    "name": "provider name",
    "courses": [
      {
        "_id": 1,
        "name": "course name",
        "requirements": [
          {
            "subjects": [
              "SubjectA::B",
              "SubjectB::B",
              "SubjectC::B"
            ]
          },
          {
            "subjects": [
              "SubjectA::B",
              "SubjectB::B",
              "SubjectC::B"
            ]
          }
        ]
      },
      {
        "_id": 1,
        "name": "course name",
        "requirements": [
          {
            "subjects": [
              "SubjectA::B",
              "SubjectB::B",
              "SubjectC::B"
            ]
          },
          {
            "subjects": [
              "SubjectA::B",
              "SubjectB::B",
              "SubjectC::B"
            ]
          }
        ]
      }
    ]
  }
]

【问题讨论】:

  • 添加预期输出

标签: javascript arrays mongodb mongoose aggregation-framework


【解决方案1】:

您可以通过以下阶段重构游览阵列,

  • $group by _idcourses._id 并获得第一个 name 和课程名字,并构造 requirements 数组
  • $group 仅由 _id 得到第一个 name 并重构 courses 数组
  {
    $group: {
      _id: {
        _id: "$_id",
        cId: "$courses._id"
      },
      name: { $first: "$name" },
      course_name: { $first: "$courses.name" },
      requirements: { $push: "$courses.requirements" }
    }
  },
  {
    $group: {
      _id: "$_id._id",
      name: { $first: "$name" },
      courses: {
        $push: {
          _id: "$_id.cId",
          name: "$course_name",
          requirements: "$requirements"
        }
      }
    }
  }

Playground

【讨论】:

  • 太好了,这真的很有帮助。那么,如果我在数千条记录上运行此管道,是否会导致数据库成本高昂?
  • 你说的高成本是什么意思?如果您在谈论性能,如果您在根目录中有更多文档,则可以,但如果您有更多嵌套文档,则会影响。
  • 是的,表现,我的期望在前几个比赛阶段之后,每个课程数组的最终结果将少于 100 个,而需求数组中的大约 2 到 3 个。这种方法在性能方面是否可行,还是不推荐。
  • 这会影响表现问题,但是,你能解释一下并分享你在小组赛之前做什么比赛吗?所以我将在没有放松和小组阶段的情况下分享另一个查询。所以之后你可以比较两个查询的性能。
  • 我能理解,但你能分享一下你在 $group 阶段之前做了什么过滤吗?你能在操场上添加它并分享我新的链接。
猜你喜欢
  • 2018-09-10
  • 2015-03-10
  • 2021-08-13
  • 2020-04-23
  • 2020-01-24
  • 2022-01-22
  • 1970-01-01
  • 2017-07-26
  • 2021-06-27
相关资源
最近更新 更多