【问题标题】:How to aggregate array of ObjectId pairs with their relevant collection如何聚合 ObjectId 对数组及其相关集合
【发布时间】:2019-09-18 18:22:59
【问题描述】:

我有一个课程集,我在其中为该课程的每个科目分配教师。分配被保存为 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"
           }
       }
   ]
}

【问题讨论】:

标签: mongodb mongoose


【解决方案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】:

    看看$lookup 聚合阶段,它可以让您加入 集合。文档中有大量的用法示例。

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

    courses.aggregate(
        [
            { 
                "$unwind" : {
                    "path" : "$allotment"
                }
            }, 
            { 
                "$lookup" : {
                    "from" : "subjects", 
                    "localField" : "allotment.subject", 
                    "foreignField" : "_id", 
                    "as" : "allotment.subject"
                }
            }, 
            { 
                "$lookup" : {
                    "from" : "teachers", 
                    "localField" : "allotment.teacher", 
                    "foreignField" : "_id", 
                    "as" : "allotment.teacher"
                }
            }, 
            { 
                "$addFields" : {
                    "allotment.subject" : {
                        "$arrayElemAt" : [
                            "$allotment.subject", 
                            0.0
                        ]
                    }, 
                    "allotment.teacher" : {
                        "$arrayElemAt" : [
                            "$allotment.teacher", 
                            0.0
                        ]
                    }
                }
            }, 
            { 
                "$group" : {
                    "_id" : "$_id", 
                    "isAssigned" : {
                        "$first" : "$isAssigned"
                    }, 
                    "name" : {
                        "$first" : "$name"
                    }, 
                    "section" : {
                        "$first" : "$section"
                    }, 
                    "allotment" : {
                        "$addToSet" : "$allotment"
                    }
                }
            }
        ]
    )
    

    【讨论】:

    • 好的,理想情况下,提供每个集合的示例文档和预期结果。然后,我们可以尝试提供解决方案。
    • 已编辑我的问题并提供了详细的见解,请查看它
    【解决方案3】:

    首先你必须$unwind allotment 数组,然后为subject 应用$lookup,然后对teachers 重复相同的操作,最后应用$group 将其组合回数组中。请参阅下面已经尝试过的聚合查询,它对我有用。

        Course.aggregate([
            {"$match": matchQuery},
            {
            $unwind: '$allotment'  
            },
            {
                $lookup:{
                "from": "subjects",
                "localField": "allotment.subject",
                "foreignField": "_id",
                "as": "allotment.subject"
                }
            },
            {
            $unwind: '$allotment.subject'  
            },
            {
                "$lookup": {
                "from": "teachers",
                "localField": "allotment.teacher",
                "foreignField": "_id",
                "as": "allotment.teacher"
                }
            },
            {
            $unwind: '$allotment.teacher'  
            },
            { 
                    "$group" : {
                        "_id" : "$_id", 
                        "isAssigned" : {
                            "$first" : "$isAssigned"
                        }, 
                        "name" : {
                            "$first" : "$name"
                        }, 
                        "section" : {
                            "$first" : "$section"
                        }, 
                        "allotment" : {
                            "$addToSet" : "$allotment"
                        }
                    }
                }
        ])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-05
      • 2014-12-10
      • 2019-04-13
      • 2018-01-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多