I'm learning to use mongodb. I made 3 collections (User, Enrollment, Courses)
User
+--------------------------------------+---------+--------+
| _id | user_id | name |
+--------------------------------------+---------+--------+
| ObjectId("5ee6c0511d0843811413b225") | 1 | John |
+--------------------------------------+---------+--------+
| ObjectId("5ef9e9b11db598099e183319") | 2 | Bob |
+--------------------------------------+---------+--------+
Courses
+--------------------------------------+---------+-----------------+
| _id | courseID| courseName |
+--------------------------------------+---------+-----------------+
| ObjectId("5ef9d1b28e08e1c04ac9530b") | "1111" | English |
+--------------------------------------+---------+-----------------+
| ObjectId("5ef9db2bdd883a3444dd396a") | "2222" | Algebra 1 |
+--------------------------------------+---------+-----------------+
| ObjectId("5ef9ea212c72182edf809a52") | "3333" | World History |
+--------------------------------------+---------+-----------------+
| ObjectId("5ee6c0511d0843811413b226") | "4444" | Algebra 2 |
+--------------------------------------+---------+-----------------+
Enrollment
+---------+----------+
| user_id | courseID |
+---------+----------+
| 1 | "1111" |
+---------+----------+
| 2 | "2222" |
+---------+----------+
| 1 | "2222" |
+---------+----------+
| 1 | "4444" |
+---------+----------+
Everytime user click on one of the courses will added into enrollment table. I am able to show the enrolled list for user, but I have no idea how to show courses that have not been enrolled by user.
I would like to know how to show courses that have not been added to enrollment table by user? I tried to use user_id: { $ne: 1 }
, but doesn't seem show the correct courses that have not been enrolled.
How to show correctly?
You can use aggregation
Assuming you know user_id
, let's say we choose Bob with user_id: 2
You can either start with getting all courses from Course
and filter only courses that the user has not enrolled
db.Course.aggregate({
$lookup: { // "join" with Enrollment
from: "Enrollment",
localField: "courseID",
foreignField: "courseID",
as: "enrollments"
},
},
{
$match: { // only match courses that user_id 2 doesn't exist in list of enrolments
"enrollments.user_id": {
$ne: 2
}
}
})
Or start with Enrollment
from a particular User
and find the courses from Course
db.Enrollment.aggregate({
$match: { // find enrolments of user_id 2
user_id: 2
}
},
{
$group: { // combine all courseID into an array
_id: "$user_id",
courseIDs: {
$push: "$courseID"
}
}
},
{
$lookup: { // "join" with Course that is not in the list of enrolments
from: "Course",
as: "notEnrolledCourses",
let: {
courseIDs: "$courseIDs"
},
pipeline: [
{
$match: {
$expr: {
$not: {
$in: [
"$courseID",
"$$courseIDs"
]
}
}
}
}
]
}
})
Note that above approaches don't have the same output structure, you will have to manipulate the to get to your desired output shape.
With this collection structure:
Step 1 : Fetch user's enrolled courses list. For eg: user 2's courses: ['2222']
Step 2 : Use find
query ( { courseID: { $nin: ['2222'] } }
) on Courses
collection to fetch un-enrolled courses list.
However, I'd suggest you to update collection's schema by either of following ways:
User
collection in an Array.Enrollment
collection.This way, you can eliminate some processing in Step 1.
Hope this helps!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.