如何聚合ObjectId对及其相关集合的数组

时间:2019-04-30 06:23:07

标签: mongodb mongoose

我有一个课程集合,在其中我为该课程的每个学科分配了老师。分配已保存为JSON数组,请查看下面的参考文档。

{
   "_id" : ObjectId("5cc7d72d8e165005cbef939e"),
   "isAssigned" : true,
   "name" : "11",
   "section" : "A",
   "allotment" : [
       {
           "subject" : ObjectId("5cc3f7cc88e95a0c8e8ccd7d"),
           "teacher" : ObjectId("5cbee0e37a3c852868ec9797")
       },
       {
           "subject" : ObjectId("5cc3f80e88e95a0c8e8ccd7e"),
           "teacher" : ObjectId("5cbee10c7a3c852868ec9798")
       }
   ]
}

我正在尝试将主题和教师字段及其来自两个不同集合的文档进行匹配。我可以将它们放在两个不同的数组中,但无法按预期输出的结构显示它们

教师收藏中的文档

{
 _id: ObjectId("5cbee0e37a3c852868ec9797"),
 name: "Alister"
}

主题文档

{
 _id: ObjectId("5cc3f7cc88e95a0c8e8ccd7d"),
 name: "English",
 code: "EN"
}

我尝试过查询

Course.aggregate([
               {"$match": matchQuery},
               {"$lookup": {
                   "from": "subjects",
                   "localField": "allotment.subject",
                   "foreignField": "_id",
                   "as": "subjectInfo"
                   }
               },
               {"$lookup": {
                   "from": "teachers",
                   "localField": "allotment.teacher",
                   "foreignField": "_id",
                   "as": "teacherInfo"}
               },
               ])

该查询的输出

{
 isAssigned: true
 name: "11"
 section: "A"
 subjectInfo:[
  {_id: "5cc3f7cc88e95a0c8e8ccd7d", name:"English", code:"EN"}
  {_id: "5cc3f80e88e95a0c8e8ccd7e", name: "Science", code:"SC"}
 ]
 teacherInfo:[
  {_id: ObjectId("5cbee0e37a3c852868ec9797"),name: "Alister"},
  { _id: ObjectId("5cbee10c7a3c852868ec9798"),name: "Frank"}
 ]
}

扩展输出

{
   "_id" : ObjectId("5cc7d72d8e165005cbef939e"),
   "isAssigned" : true,
   "name" : "11",
   "section" : "A",
   "allotment" : [
       {
           "subject" : {
             _id: ObjectId("5cc3f7cc88e95a0c8e8ccd7d"),
             name: "English",
             code: "EN"
           }
           "teacher" : {
              _id: ObjectId("5cbee0e37a3c852868ec9797"),
              name: "Alister"
           }
       },
       {
           "subject" : {
             _id: ObjectId("5cc3f80e88e95a0c8e8ccd7e"),
             name: "Science",
             code: "SC"
           }
           "teacher" : {
              _id: ObjectId("5cbee10c7a3c852868ec9798"),
              name: "Frank"
           }
       }
   ]
}

3 个答案:

答案 0 :(得分:2)

看看$lookup聚合阶段,它可以让您加入集合。文档中有很多使用示例。

编辑:以下是应提供预期结果的完整管道:

TypeError: graphqlX is not a function

答案 1 :(得分:1)

只需在查找之前展开数组:

Course.aggregate([
               {"$match": matchQuery},
               {"$unwind: "$allotment"}
               {"$lookup": {
                   "from": "subjects",
                   "localField": "allotment.subject",
                   "foreignField": "_id",
                   "as": "subjectInfo"
                   }
               },
               {"$lookup": {
                   "from": "teachers",
                   "localField": "allotment.teacher",
                   "foreignField": "_id",
                   "as": "teacherInfo"}
               },
               ])

如果您要在此之后重新分组以恢复预期格式,则可以添加:

{ $group : { 
         _id: "$_id",
         name: {$first: "$name"},
         section: {$first: "$section},
         isAssigned: {$first: "$isAssigned},
         allotment: {$push: {teacher: "$teacherInfo.0", subject: "$subjectInfo.0"}}

我假设TeacherInfo和subjectInfo从不为空,如果不是这种情况,则应添加$ match来过滤空的。

答案 2 :(得分:1)

首先,您必须$unwind allotment数组,然后对$lookup应用subject,然后对teachers重复同样的操作,最后应用{{1} }将其组合回数组中。请参阅下面的汇总查询,它已经尝试过并且对我有用。

$group