2017-09-25 53 views
2

我一直在嘗試在SO上找到的每一個方法,但都沒有成功。試圖 完成一個看似簡單的任務(很容易使用JSON /例如lodash)MongoDB中..MongoDB>從嵌套數組提取集合

我有一個集合: db.users>

[ 
    { 
     _id: 'userid', 
     profile: { 
      username: 'abc', 
      tests: [ 
       { 
        _id: 'testid', 
        meta: { 
         category: 'math', 
         date: '9/2/2017', 
         ... 
        } 
        questions: [ 
         { 
          type: 'add', 
          correct: true, 
         }, 
         { 
          type: 'subtract', 
          correct: true, 
         }, 
         { 
          type: 'add', 
          correct: false, 
         }, 
         { 
          type: 'multiply', 
          correct: false, 
         }, 

        ] 
       }, 
       ... 
      ] 
     } 
    }, 
    ... 
] 

我想用落得陣列由問題類型分組:

[ 
    { 
     type: 'add', 
     correct: 5, 
     wrong: 3, 
    }, 
    { 
     type: 'subtract', 
     correct: 4, 
     wrong: 9 
    } 
    ... 
] 

我試圖骨料的不同變型中,最後一個是:

db.users.aggregate([ 
    { $match: { 'profile.tests.meta.category': 'math' }}, 
    { 
     $project: { 
      tests: { 
       $filter: { 
        input: "$profile.tests", 
        as: "test", 
        cond: { $eq: ['$$test.meta.category', 'math'] } 
       } 
      } 
     } 
    }, 
    { 
     $project: { 
      question: "$tests.questions" 
     } 
    }, 
    { $unwind: "$questions"}, 

]) 

還試圖在管道末端添加$組:

{ 
     $group: 
     { 
      _id: '$questions.type', 
      res: { 
       $addToSet: { correct: {$eq:['$questions.chosenAnswer', '$questions.answers.correct'] } 
      } 
     } 
    } 

沒有變化給了我什麼我尋找,我敢肯定,我錯過了一個核心概念,我看過了文檔,並不能找出它..我基本上是尋找一個flatMap來提取所有用戶的所有問題,並按類型分組。

如果有人能帶領我走向正確的方向,我會非常感謝它:) thx。 (另外,我使用Meteor,所以任何查詢都必須在Meteor mongo中工作)

+0

對不起,只有複製相關的領域,但它是一個錯誤,應該是元>類別>數學,而不是僅僅類..我會更新的Q,THX – webkit

回答

2

您可以在3.4中嘗試下面的聚合。

$filter過濾math類別與$map投射在每個匹配類別,接着$reduce$concatArrays得到所有questions成單個陣列,用於所有匹配的類別questions陣列。

$unwind問題陣列和$group通過type$sum計算correctwrong計數。

db.users.aggregate([ 
    { 
    "$match": { 
     "profile.tests.meta.category": "math" 
    } 
    }, 
    { 
    "$project": { 
     "questions": { 
     "$reduce": { 
      "input": { 
      "$map": { 
       "input": { 
       "$filter": { 
        "input": "$profile.tests", 
        "as": "testf", 
        "cond": { 
        "$eq": [ 
         "$$testf.meta.category", 
         "math" 
        ] 
        } 
       } 
       }, 
       "as": "testm", 
       "in": "$$testm.questions" 
      } 
      }, 
      "initialValue": [], 
      "in": { 
      "$concatArrays": [ 
       "$$value", 
       "$$this" 
      ] 
      } 
     } 
     } 
    } 
    }, 
    { 
    "$unwind": "$questions" 
    }, 
    { 
    "$group": { 
     "_id": "$questions.type", 
     "correct": { 
     "$sum": { 
      "$cond": [ 
      { 
       "$eq": [ 
       "$questions.correct", 
       true 
       ] 
      }, 
      1, 
      0 
      ] 
     } 
     }, 
     "wrong": { 
     "$sum": { 
      "$cond": [ 
      { 
       "$eq": [ 
       "$questions.correct", 
       false 
       ] 
      }, 
      1, 
      0 
      ] 
     } 
     } 
    } 
    } 
]) 
+1

你認真讓我很快樂..感謝您抽出寶貴時間。 – webkit

+0

我是MongoDB的新手,試圖準確理解你所做的事情,深入研究$ reduce當然:),看起來這個查詢在測試時實際上運行得非常快,你有任何提示進一步優化嗎?我知道索引應該創建,在這裏有關嗎?我被告知將所有問題提取到他們自己的收藏集中。這是你在這種情況下會提出的一些建議嗎?或者他們在哪裏?謝謝。 – webkit

+0

Np。您只能在'$ match'階段使用索引。所以爲'profile.tests.meta.category'添加索引。在選擇一個之前,你必須測試所有的選項。我還會嘗試將問題移到頂層,並將其與相關元數據放入其自己的數組中,以將其綁定回相關測試(實質上覆制一些數據)。你現在也可以在需要的時候添加'$ match'來解決問題。將此選項與當前的結構和選項進行比較,並將其移入自己的集合中。 – Veeram