MongoDB聚合查询 - 返回嵌套子文档中的所有项目

Posted

技术标签:

【中文标题】MongoDB聚合查询 - 返回嵌套子文档中的所有项目【英文标题】:MongoDB aggregation query - return all items inside nested subdocument 【发布时间】:2021-07-27 08:26:50 【问题描述】:

基本上,我有一个嵌套的对象数组。我想从这些对象中提取信息,并将所有结果作为数组返回。

这是我的数据:

[
  
    "_id": "608642db80a36336946620aa",
    "title": "titleHere",
    "types": 
      "flashcardReversed": [
        
          "normal":  // the data inside of "normal" should become its own object in the returned array
            "_id": "608d5b290e635ece6828141X",
            "front": "2front",
            "back": "2back"
          ,
          "reversed":  // the data inside of "reversed" should become its own object in the returned array
            "_id": "608t5b290e635ece6828141Y",
            "front": "2frontReversed",
            "back": "2backReversed"
          
        ,
        
          "normal": 
            "_id": "608a5b31a3f9806de253726X",
            "front": "2front2",
            "back": "2back2"
          ,
          "reversed": 
            "_id": "608a5b31a3f9806de253726Y",
            "front": "2frontReversed2",
            "back": "2backReversed2"
          
        
      ]
    
  
]

这是想要的结果:

[
  
    "flashcardReversed": [
      
        "_id": "608d5b290e635ece6828141X",
        "front": "2front",
        "back": "2back"
      ,
      
        "_id": "608t5b290e635ece6828141Y",
        "front": "2frontReversed",
        "back": "2backReversed"
      ,
      
        "_id": "608t5b290e635ece6828141Y",
        "front": "2frontReversed",
        "back": "2backReversed"
      ,
      
        "_id": "608a5b31a3f9806de253726Y",
        "front": "2frontReversed2",
        "back": "2backReversed2"
      
    ]
  
]

我目前的尝试:https://mongoplayground.net/p/k3Fjd59KMKg 我曾尝试通过各种方法合并$card$card2 文档,然后使用$replaceRoot 来创建所需的结果 - 但经过长时间的尝试,我没有成功。

关于我的用例的一些说明 - 我将在$facet 中使用这个管道 flashcardReversed 内部会有很多对象,都是从同一个 Mongoose Schema 创建的

文档最多应包含 ~2000 张卡片。我需要在反应网站中使用的结果。我应该担心这个搜索的效率吗? (如果这本身就是一个问题,我很乐意将其移动)。

如果我的 Mongoose Schema 有帮助,请告诉我,我可以添加它们。

感谢所有帮助,

- Riley Swinson

【问题讨论】:

原版中是否总是“正常”和“反转”键?还是可以有更多? @CodyG 可以有很多文档,都具有相同的结构。我会澄清我的帖子。谢谢! 【参考方案1】:

我能够想出这个查询来得到想要的结果

    db.collection.aggregate([
  
    "$unwind": "$types.flashcardReversed"
  ,
  
    "$project": 
      "flashcardReversed": 
        "$map": 
          "input": 
            "$objectToArray": "$types.flashcardReversed"
          ,
          "as": "elem",
          "in": "$$elem.v"
        
      
    
  ,
  
    "$unwind": "$flashcardReversed"
  ,
  
    "$group": 
      "_id": 1,
      "flashcardReversed": 
        "$push": "$flashcardReversed"
      
    
  ,
  
    "$project": 
      "_id": 0
    
  
])

上述管道的解释:

    使用$unwind 将数组划分为其元素 使用$project$mapflashcardReversed 对象转换为值数组。使用$map 允许管道处理正常和反转之上的任何其他键 使用$unwind再次拆分步骤2中形成的flashcardReversed数组 使用 $group$push 累加器将 flashcardReversed 的所有值添加到单个数组中 使用$project 从响应中删除_id 字段

这是一个 Mongodb 游乐场link 相同

【讨论】:

【参考方案2】:

这可以通过

$unwind 拆分闪存卡阵列 $project 将包含 normal/reverse 的对象转换为数组 $unwind 创建的数组 $group by _id 并收集数组中的值
db.collection.aggregate([
  $unwind: "$types.flashcardReversed",
  $project: 
      flashcardReversed: [
        "$types.flashcardReversed.normal",
        "$types.flashcardReversed.reversed"
      ]
  ,
  $unwind: "$flashcardReversed",
  $group: 
      _id: "$_id",
      flashcardReversed: $push: "$flashcardReversed"
  
])

【讨论】:

感谢您的回答 - 我很感激。我注意到我的问题中有一个错误——因为我使用的是$facet,所以我已经有了"flashcardReversed" as the parent: []。我将如何在结果中返回 flashcardReversed 数组中的内容? 使用 $replaceRoot 阶段 已尝试,但出现错误 $replaceRoot must be of type object。尝试使用 $arrayToObject,但我认为我需要一个不同的对象结构才能工作? $replaceRoot:newRoot:"$flashcardReversed" 是的,正是我尝试过的,但仍然返回错误 - mongoplayground.net/p/CiaOOrzzw5i。目标是从数组中删除所有内容 - 因为 $facet 已经是一个数组 this 似乎它可能是一个解决方案

以上是关于MongoDB聚合查询 - 返回嵌套子文档中的所有项目的主要内容,如果未能解决你的问题,请参考以下文章

如何在不同深度内搜索 MongoDB 嵌套子文档

如何在不同深度内搜索 MongoDB 嵌套子文档

使用 arrayFilters 更新 MongoDB 中的嵌套子文档

匹配 MongoDB 中嵌套子文档的嵌套数组

mongodb中在嵌套子文档的文档上面建立索引

Elasticsearch聚合查询