如何在 mongodb 聚合中展开嵌套对象数组?

Posted

技术标签:

【中文标题】如何在 mongodb 聚合中展开嵌套对象数组?【英文标题】:How to unwind nested object arrays in mongodb aggregation? 【发布时间】: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"
            ]
          
        ]
      
    ]
  
]

【问题讨论】:

添加预期输出 【参考方案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 阶段之前做了什么过滤吗?你能在操场上添加它并分享我新的链接。

以上是关于如何在 mongodb 聚合中展开嵌套对象数组?的主要内容,如果未能解决你的问题,请参考以下文章

如何仅在猫鼬中使用聚合填充嵌套在对象数组中的字段?

具有嵌套对象数组的 MongoDB 聚合

MongoDB:如何使用查找查询填充嵌套对象?

MongoDB 聚合与嵌套的对象属性数组与日期

如何从 1 分钟的嵌套数组数据中聚合 OHLC 5 分钟(mongodb、mongoose)

如何在spring数据mongodb中聚合一个嵌套对象并避免PropertyReferenceException?