MongoDB查找(JOIN),带有双嵌套数组中的字段

发布于 2025-02-06 12:51:22 字数 2338 浏览 0 评论 0 原文

使用MongoDB集合名称部门带有以下结构:

{
  "_id":99,
  "name":"Erick Kalewe",
  "faculty":"Zazio",
  "lecturers":[
    {
      "lecturerID":31,
      "name":"Granny Kinton",
      "email":"[email protected]",
      "imparts":[
        {
          "groupID":70,
          "codCourse":99
        }
      ]
    },
    {
      "lecturerID":36,
      "name":"Michale Dahmel",
      "email":"[email protected]",
      "imparts":[
        {
          "groupID":100,
          "codCourse":60
        }
      ]
    }
  ]
}

另一个集合带有此结构:

{
  "_id":100,
  "codCourse":11,
  "language":"Romanian",
  "max_students":196,
  "students":[
    {
      "studentID":1
    }
  ],
  "classes":[
    {
      "date":datetime.datetime(2022, 5, 10, 4, 24, 19),
      "cod_classroom":100
    }
  ]
}

加入它们以获取以下内容:

{
  "_id":99,
  "name":"Erick Kalewe",
  "faculty":"Zazio",
  "lecturers":[
    {
      "lecturerID":31,
      "name":"Granny Kinton",
      "email":"[email protected]",
      "imparts":[
        {
          "groupID":70,
          "codCourse":99
        }
      ]
    },
    {
      "lecturerID":36,
      "name":"Michale Dahmel",
      "email":"[email protected]",
      "imparts":[
        {
          "_id":100,
          "codCourse":11,
          "language":"Romanian",
          "max_students":196,
          "students":[
            {
              "studentID":1
            }
          ],
          "classes":[
            {
              "date":datetime.datetime(2022, 5, 10, 4, 24, 19),
              "cod_classroom":100
            }
          ]
        }
      ]
    }
  ]
}

目标是获取带有号码的报告由一位教授教授的学生。

With a MongoDB collection name department with the following structure:

{
  "_id":99,
  "name":"Erick Kalewe",
  "faculty":"Zazio",
  "lecturers":[
    {
      "lecturerID":31,
      "name":"Granny Kinton",
      "email":"[email protected]",
      "imparts":[
        {
          "groupID":70,
          "codCourse":99
        }
      ]
    },
    {
      "lecturerID":36,
      "name":"Michale Dahmel",
      "email":"[email protected]",
      "imparts":[
        {
          "groupID":100,
          "codCourse":60
        }
      ]
    }
  ]
}

and another collection group with this structure:

{
  "_id":100,
  "codCourse":11,
  "language":"Romanian",
  "max_students":196,
  "students":[
    {
      "studentID":1
    }
  ],
  "classes":[
    {
      "date":datetime.datetime(2022, 5, 10, 4, 24, 19),
      "cod_classroom":100
    }
  ]
}

join them to get the following:

{
  "_id":99,
  "name":"Erick Kalewe",
  "faculty":"Zazio",
  "lecturers":[
    {
      "lecturerID":31,
      "name":"Granny Kinton",
      "email":"[email protected]",
      "imparts":[
        {
          "groupID":70,
          "codCourse":99
        }
      ]
    },
    {
      "lecturerID":36,
      "name":"Michale Dahmel",
      "email":"[email protected]",
      "imparts":[
        {
          "_id":100,
          "codCourse":11,
          "language":"Romanian",
          "max_students":196,
          "students":[
            {
              "studentID":1
            }
          ],
          "classes":[
            {
              "date":datetime.datetime(2022, 5, 10, 4, 24, 19),
              "cod_classroom":100
            }
          ]
        }
      ]
    }
  ]
}

The objective is to get a report with the number of students taught by a professor from a department.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

じее 2025-02-13 12:51:23

查询

  • 放松一下,进行加入,然后重新组备份
  • 其大查询,因为您想加入嵌套领域,这意味着2个放松和2个分组以还原结构
    (我认为总体上加入字段不应该深入内部)
  • 放松两个阵列
  • 在GroupID上进行查找
  • ,现在将文档构造为2级,
  • 首先嵌套了它的影响,其影响需要分组和推开
    (对于休息参数,我先保留$)
    我们还根据评论将学生总结,
  • 然后是我需要分组并推动的讲师
    (对于休息论点,我先保留$)
    我们与该系的最高学生一起演讲
    (MongoDB也可以比较文档)

IN/OUT )

department.aggregate(
[{"$unwind": "$lecturers"}, {"$unwind": "$lecturers.imparts"},
 {"$lookup": 
   {"from": "coll",
    "localField": "lecturers.imparts.groupID",
    "foreignField": "_id",
    "as": "lecturers.imparts"}},
 {"$set": {"lecturers.imparts": {"$first": "$lecturers.imparts"}}},
 {"$group": 
   {"_id": {"_id": "$_id", "lecturersID": "$lecturers.lecturerID"},
    "name": {"$first": "$name"},
    "faculty": {"$first": "$faculty"},
    "lecturers": 
     {"$first": 
       {"lecturerID": "$lecturers.lecturerID",
        "name": "$lecturers.name",
        "email": "$lecturers.email"}},
    "imparts": {"$push": "$lecturers.imparts"},
    "lecture_max_students": 
     {"$sum": "$lecturers.imparts.max_students"}}},
 {"$set": 
   {"lecturers": 
     {"$mergeObjects": 
       ["$lecturers", {"imparts": "$imparts"},
         {"lecture_max_students": "$lecture_max_students"}]},
    "imparts": "$REMOVE","lecture_max_students": "$REMOVE"}},
 {"$group": 
   {"_id": "$_id._id",
    "name": {"$first": "$name"},
    "faculty": {"$first": "$faculty"},
    "lectures": {"$push": "$lecturers"},
    "dept-max-lecturer": 
     {"$max": {"max-students": "$lecturers.lecture_max_students",
               "lecturerID": "$lecturers.lecturerID"}}}}])

Query

  • unwind, do the join, and re-group back
  • its kinda big query because you want to join in nested field, and this means 2 unwind and 2 groupings to restore the structure
    (i think in general joining fields shouldn't go deep inside)
  • unwind both arrays
  • do the lookup on groupID
  • and now construct back the document as 2 level nested
  • first its impacts that need to be grouped and pushed
    (for rest argument i keep the $first)
    we sum also the students based on the comment
  • then its lecturers that i need to be grouped and pushed
    (for rest arguments i keep the $first)
    we take the lecture with the max students in the department
    (mongodb can compare documents also)

Playmongo (you can put your mouse at the end of each stage to see in/out of that stage)

department.aggregate(
[{"$unwind": "$lecturers"}, {"$unwind": "$lecturers.imparts"},
 {"$lookup": 
   {"from": "coll",
    "localField": "lecturers.imparts.groupID",
    "foreignField": "_id",
    "as": "lecturers.imparts"}},
 {"$set": {"lecturers.imparts": {"$first": "$lecturers.imparts"}}},
 {"$group": 
   {"_id": {"_id": "$_id", "lecturersID": "$lecturers.lecturerID"},
    "name": {"$first": "$name"},
    "faculty": {"$first": "$faculty"},
    "lecturers": 
     {"$first": 
       {"lecturerID": "$lecturers.lecturerID",
        "name": "$lecturers.name",
        "email": "$lecturers.email"}},
    "imparts": {"$push": "$lecturers.imparts"},
    "lecture_max_students": 
     {"$sum": "$lecturers.imparts.max_students"}}},
 {"$set": 
   {"lecturers": 
     {"$mergeObjects": 
       ["$lecturers", {"imparts": "$imparts"},
         {"lecture_max_students": "$lecture_max_students"}]},
    "imparts": "$REMOVE","lecture_max_students": "$REMOVE"}},
 {"$group": 
   {"_id": "$_id._id",
    "name": {"$first": "$name"},
    "faculty": {"$first": "$faculty"},
    "lectures": {"$push": "$lecturers"},
    "dept-max-lecturer": 
     {"$max": {"max-students": "$lecturers.lecture_max_students",
               "lecturerID": "$lecturers.lecturerID"}}}}])
一向肩并 2025-02-13 12:51:23

现在我们已经了解了一个问题(根据您的其他问题),答案可以是) :

  1. 添加每个部门记录其所有相关组的集合。
  2. $查找仅为每个组创建 groups 数组的学生ID。
  3. 将相关的数据插入每个讲师
  4. 的唯一学生
  5. 计算 maximpartsStudents ,这是来自其所有 groups groups $ ydard $ redion 讲师数组仅包括讲师带有最高 maximpartsstudents
  6. 格式化的答案
db.department.aggregate([
  {
    $addFields: {
      groups: {
        $setIntersection: [
          {
            $reduce: {
              input: "$lecturers.imparts.groupID",
              initialValue: [],
              in: {$concatArrays: ["$value", "$this"]}
            }
          }
        ]
      }
    }
  },
  {
    $lookup: {
      from: "group",
      let: {groupIDs: "$groups"},
      pipeline: [
        {$match: {$expr: {$in: ["$_id", "$groupIDs"]}}},
        {
          $project: {
            students: {
              $reduce: {
                input: "$students",
                initialValue: [],
                in: {$concatArrays: ["$value", ["$this.studentID"]]}
              }
            }
          }
        }
      ],
      as: "groups"
    }
  },
  {
    $project: {
      name: 1,
      lecturers: {
        $map: {
          input: "$lecturers",
          in: {
            $mergeObjects: [
              {lecturerID: "$this.lecturerID"},
              {groups: {
                  $map: {
                    input: "$this.imparts",
                    in: {
                      $arrayElemAt: [
                        "$groups",
                        {$indexOfArray: ["$groups._id", "$this.groupID"]}
                      ]
                    }
                  }
                }
              }
            ]
          }
        }
      }
    }
  },
  {
    $project: {
      name: 1,
      lecturers: {
        $map: {
          input: "$lecturers",
          as: "item",
          in: {
            $mergeObjects: [
              {
                maxImpartsStudents: {
                  $size: {
                    $reduce: {
                      input: "$item.groups",
                      initialValue: [],
                      in: {$setUnion: ["$value", "$this.students"]}
                    }
                  }
                }
              },
              {lecturerID: "$item.lecturerID"}
            ]
          }
        }
      }
    }
  },
  {
    $set: {
      lecturers: {
        $reduce: {
          input: "$lecturers",
          initialValue: {
            "maxImpartsStudents": 0
          },
          in: {
            $cond: [
              {$gte: ["$this.maxImpartsStudents", "$value.maxImpartsStudents"]},
              "$this", "$value"
            ]
          }
        }
      }
    }
  },
  {
    $project: {
      lecturerID: "$lecturers.lecturerID",
      maxImpartsStudents: "$lecturers.maxImpartsStudents",
      departmentName: "$name"
    }
  }
])

比结合两个问题的解决方案要好得多。

请查看其在

Now that we understand the question (according to your other question), an answer can be:

  1. Add each department document a set of all its relevant groups.
  2. $lookup only the student ids for each group to create a groups array.
  3. Insert the relevant groups data to each lecturer.
  4. Calculate maxImpartsStudents which is the number of unique students per lecturer from all of its groups
  5. $reduce the lecturers array to include only the lecturer with highest maxImpartsStudents.
  6. Format the answer
db.department.aggregate([
  {
    $addFields: {
      groups: {
        $setIntersection: [
          {
            $reduce: {
              input: "$lecturers.imparts.groupID",
              initialValue: [],
              in: {$concatArrays: ["$value", "$this"]}
            }
          }
        ]
      }
    }
  },
  {
    $lookup: {
      from: "group",
      let: {groupIDs: "$groups"},
      pipeline: [
        {$match: {$expr: {$in: ["$_id", "$groupIDs"]}}},
        {
          $project: {
            students: {
              $reduce: {
                input: "$students",
                initialValue: [],
                in: {$concatArrays: ["$value", ["$this.studentID"]]}
              }
            }
          }
        }
      ],
      as: "groups"
    }
  },
  {
    $project: {
      name: 1,
      lecturers: {
        $map: {
          input: "$lecturers",
          in: {
            $mergeObjects: [
              {lecturerID: "$this.lecturerID"},
              {groups: {
                  $map: {
                    input: "$this.imparts",
                    in: {
                      $arrayElemAt: [
                        "$groups",
                        {$indexOfArray: ["$groups._id", "$this.groupID"]}
                      ]
                    }
                  }
                }
              }
            ]
          }
        }
      }
    }
  },
  {
    $project: {
      name: 1,
      lecturers: {
        $map: {
          input: "$lecturers",
          as: "item",
          in: {
            $mergeObjects: [
              {
                maxImpartsStudents: {
                  $size: {
                    $reduce: {
                      input: "$item.groups",
                      initialValue: [],
                      in: {$setUnion: ["$value", "$this.students"]}
                    }
                  }
                }
              },
              {lecturerID: "$item.lecturerID"}
            ]
          }
        }
      }
    }
  },
  {
    $set: {
      lecturers: {
        $reduce: {
          input: "$lecturers",
          initialValue: {
            "maxImpartsStudents": 0
          },
          in: {
            $cond: [
              {$gte: ["$this.maxImpartsStudents", "$value.maxImpartsStudents"]},
              "$this", "$value"
            ]
          }
        }
      }
    }
  },
  {
    $project: {
      lecturerID: "$lecturers.lecturerID",
      maxImpartsStudents: "$lecturers.maxImpartsStudents",
      departmentName: "$name"
    }
  }
])

Which is much better than combining the solutions from both questions.

See how it works on the playground example

纵性 2025-02-13 12:51:22

You can try aggregation framework,

  • $lookup with group collection pass lecturers.imparts.groupID as localField and pass <代码> _id AS foreffield
  • $ addfields to merge group group imports 和remove group 字段,因为不需要
  • $ map 要迭代讲师 array> array
  • $ mergeObject 以合并的当前对象讲师 imports $ map 的更新对象
  • ,要迭代 imports array array
  • $ mergeObjects 合并的当前对象导入,并从 group
  • $ filter 找到 group> group array的循环并通过 groupId
  • $ arrayElemat 从上面过滤结果获取第一个元素
db.department.aggregate([
  {
    $lookup: {
      from: "group",
      localField: "lecturers.imparts.groupID",
      foreignField: "_id",
      as: "group"
    }
  },
  {
    $addFields: {
      lecturers: {
        $map: {
          input: "$lecturers",
          in: {
            $mergeObjects: [
              "$this",
              {
                imparts: {
                  $map: {
                    input: "$this.imparts",
                    as: "i",
                    in: {
                      $mergeObjects: [
                        "$i",
                        {
                          $arrayElemAt: [
                            {
                              $filter: {
                                input: "$group",
                                cond: { $eq: ["$this._id", "$i.groupID"] }
                              }
                            },
                            0
                          ]
                        }
                      ]
                    }
                  }
                }
              }
            ]
          }
        }
      },
      group: "$REMOVE"
    }
  }
])

You can try aggregation framework,

  • $lookup with group collection pass lecturers.imparts.groupID as localField and pass _id as foreignField
  • $addFields to merge group data with imports and remove group fields because it is not needed
  • $map to iterate loop of lecturers array
  • $mergeObjects to merge current object of lecturers and updated object of imports
  • $map to iterate loop of imports array
  • $mergeObjects to merge current object of imports and found result from group
  • $filter to iterate loop of group array and find the group by groupID
  • $arrayElemAt to get first element from above filtered result
db.department.aggregate([
  {
    $lookup: {
      from: "group",
      localField: "lecturers.imparts.groupID",
      foreignField: "_id",
      as: "group"
    }
  },
  {
    $addFields: {
      lecturers: {
        $map: {
          input: "$lecturers",
          in: {
            $mergeObjects: [
              "$this",
              {
                imparts: {
                  $map: {
                    input: "$this.imparts",
                    as: "i",
                    in: {
                      $mergeObjects: [
                        "$i",
                        {
                          $arrayElemAt: [
                            {
                              $filter: {
                                input: "$group",
                                cond: { $eq: ["$this._id", "$i.groupID"] }
                              }
                            },
                            0
                          ]
                        }
                      ]
                    }
                  }
                }
              }
            ]
          }
        }
      },
      group: "$REMOVE"
    }
  }
])

Playground

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文