MongoDB聚合以根据同一集合中所有文档的对象数组中存在的ID筛选列表。

huangapple go评论92阅读模式
英文:

MongoDb aggregation for filtering list based on ids present in object of array from all document of same collection

问题

在我的mongodb中,数据如下所示:

{
  "studentId": "a1",
  "name": "John Doe",
  "studentsReferred": [    
    {
      "course": "BTECH",
      "students": [
        {
          "studentId": "a2"
        },
        {
          "studentId": "a3"
        }
      ]
    },
	{
      "course": "MTECH",
      "students": [        
        {
          "studentId": "a4"
        },
        {
          "studentId": "a5"
        }
      ]
    }
  ]
},
{
  "studentId": "a2",
  "name": "Joseph",
  "studentsReferred": [    
    {
      "course": "BTECH",
      "students": [
        {
          "studentId": "a6"
        }
      ]
    }
  ]
}

上述JSON包含MongoDB集合中的文档。每个文档包含学生的所有详细信息以及推荐详情摘要。即,对于每个学生,都有一个包含由该学生引荐的所有学生的字段studentsReferred

我想在检索单个学生时显示该学生的所有详细信息以及被引荐的学生的姓名,如下所示:

{
  "studentId": "a1",
  "name": "John Doe",
  "studentsReferred": [    
    {
      "course": "BTECH",
      "students": [
        {
          "studentId": "a2",
		  "name": "Joseph"
        },
        {
          "studentId": "a3",
		  "name": "Lorem Ipsum"
        }
      ]
    },
	{
      "course": "MTECH",
      "students": [        
        {
          "studentId": "a4",
		  "name": "Lorem Ipsum"
        },
        {
          "studentId": "a5",
		  "name": "Lorem Ipsum"
        }
      ]
    }
  ]
}

我尝试使用MongoDB聚合来解决这个问题。但不幸的是,我无法为此编写查询。所以我们可以使用聚合来实现上述情景吗?

英文:

In my mongodb I have the data as shown below:

{
  "studentId": "a1",
  "name":"John Doe"
  "studentsReffered": [    
    {
      "course": "BTECH",
      "students": [
        {
          "studentId": "a2"
        },
        {
          "studentId": "a3"
        }
      ]
    },
	{
      "course": "MTECH",
      "students": [        
        {
          "studentId": "a4"
        },
        {
          "studentId": "a5"
        }
      ]
    }
  ]
},
{
  "studentId": "a2",
  "name":"Joseph"
  "studentsReffered": [    
    {
      "course": "BTECH",
      "students": [
        {
          "studentId": "a6"
        }
      ]
    }
  ]
}

Above JSON contains documents in collection of MongoDB. Each document contains all details of student along with referral detail summary. i.e. for every student there is a field studentsReferred which contain ids of all students which are referred by the student.

I want to show all details of student alone with the name of students which are reffered while retrieving the single student. As below

{
  "studentId": "a1",
  "name":"John Doe"
  "studentsReffered": [    
    {
      "course": "BTECH",
      "students": [
        {
          "studentId": "a2",
		  "name":"Joseph"
        },
        {
          "studentId": "a3",
		  "name":"Lorem Ipsum"
        }
      ]
    },
	{
      "course": "MTECH",
      "students": [        
        {
          "studentId": "a4",
		  "name":"Lorem Ipsum"
        },
        {
          "studentId": "a5",
		  "name":"Lorem Ipsum"
        }
      ]
    }
  ]
}

I have tried to use mongodb aggregation for this problem. But unfortunately I am not able write query for that. So can we achieve the above scenario using aggregation.

答案1

得分: 2

你可以尝试以下操作:

  • 使用$facet 创建两个数组,users 包含用户详细信息的姓名和学生ID,第二个数组是所有用户的详细信息 allUsers
  • 使用 $project 进行迭代循环
    • 使用 $map 处理 allUsers 数组作为输入
    • 使用 $map 处理 studentsReffered 数组作为输入
    • 使用 $map 处理 students 数组作为输入
    • 使用 $reduce 在条件匹配时从 users 数组中获取学生数据
  • 使用 $unwind 展开 allUsers 数组
  • 使用 $replaceWithallUsers 对象替换为根对象
db.collection.aggregate([
  {
    $facet: {
      users: [
        {
          $project: {
            studentId: 1,
            name: 1
            // 添加所需的字段,它们会自动反映在连接中
          }
        }
      ],
      allUsers: []
    }
  },
  {
    $project: {
      allUsers: {
        $map: {
          input: "$allUsers",
          in: {
            $mergeObjects: [
              "$$this",
              {
                studentsReferred: {
                  $map: {
                    input: "$$this.studentsReferred",
                    in: {
                      $mergeObjects: [
                        "$$this",
                        {
                          students: {
                            $map: {
                              input: "$$this.students",
                              as: "s",
                              in: {
                                $reduce: {
                                  input: "$users",
                                  initialValue: { studentId: "$$s.studentId" },
                                  in: {
                                    $cond: [
                                      { $eq: ["$$this.studentId", "$$s.studentId"] },
                                      "$$this",
                                      "$$value"
                                    ]
                                  }
                                }
                              }
                            }
                          }
                        }
                      ]
                    }
                  }
                }
              }
            ]
          }
        }
      }
    }
  },
  { $unwind: "$allUsers" },
  { $replaceWith: "$allUsers" }
])

Playground

英文:

You can try,

  • $facet to create 2 arrays, users user details name and studentId, second all users details in allUsers
  • $project iterate loop
    • $map input as allUsers array
    • $map input as studentsReffered array
    • $map input as students array
    • $reduce to get data of the student from users array when condition match
  • $unwind deconstruct allUsers array
  • $replaceWith replace allUsers object in root
db.collection.aggregate([
  {
    $facet: {
      users: [
        {
          $project: {
            studentId: 1,
            name: 1
            // add fields as you want it will automatically reflect in join
          }
        }
      ],
      allUsers: []
    }
  },
  {
    $project: {
      allUsers: {
        $map: {
          input: "$allUsers",
          in: {
            $mergeObjects: [
              "$$this",
              {
                studentsReffered: {
                  $map: {
                    input: "$$this.studentsReffered",
                    in: {
                      $mergeObjects: [
                        "$$this",
                        {
                          students: {
                            $map: {
                              input: "$$this.students",
                              as: "s",
                              in: {
                                $reduce: {
                                  input: "$users",
                                  initialValue: { studentId: "$$s.studentId" },
                                  in: {
                                    $cond: [
                                      { $eq: ["$$this.studentId", "$$s.studentId"] },
                                      "$$this",
                                      "$$value"
                                    ]
                                  }
                                }
                              }
                            }
                          }
                        }
                      ]
                    }
                  }
                }
              }
            ]
          }
        }
      }
    }
  },
  { $unwind: "$allUsers" },
  { $replaceWith: "$allUsers" }
])

Playground

huangapple
  • 本文由 发表于 2020年10月1日 23:46:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/64158838.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定