#mongodb #mongoose #mongodb-query #aggregation-framework #aggregate
Вопрос:
Я пытаюсь создать сводный код, который может объединять несколько коллекций и извлекать данные на основе условия
Мои коллекции выглядят следующим образом
Коллекция пользователей(Пример Документа)
{
"_id":{"$oid":"6137038058d4632824c84872"},
"first_name":"test",
"last_name":".",
"email":"valid@gmail.com",
"enrolled_courses":[
{
"completed_lessons":[],
"completed":false,
"_id": {"$oid":"6142d1c76d657428903420db"},
"course_id":{"$oid":"614033510a61aa1f3c8b94ff"}
},
{
"completed_lessons":[],
"completed":false,
"_id":{"$oid":"6156d686dcbc58503c7ec679"},
"course_id":{"$oid":"61486e57460b5a422c6e63ca"}
},
{
"completed_lessons":["616d181e62cb265db07d9273","616d182e62cb265db07d9293"],
"completed":false,
"_id":{"$oid":"616d2424149936380c186c2d"},
"course_id":{"$oid":"616d105662cb265db07d91cf"}
}
]
}
Коллекция Курсов(Пример Документа)
{
"_id":{"$oid":"6135f735b399f03ba03d74ce"},
"type":1,
"enrolled_users":["61374040c27237b1ed87480b"],
"is_deleted":0,
"status":1,
"company_id":{"$oid":"6135f6c9b399f03ba03d74a0"},
"course":"Course 1"
}
Коллекция Модулей(Пример Документа)
{
"_id":{"$oid":"616d17fd62cb265db07d9240"},
"type":1,
"is_always_available":false,
"is_deleted":0,
"status":1,
"company_id":{"$oid":"6135f6c9b399f03ba03d74a0"},
"course_id":{"$oid":"616d105662cb265db07d91cf"},
"module_name":"module 3",
"due_date":{"$date":"2021-10-18T00:00:00.000Z"}
}
Сборник уроков(Пример Документа)
{
"_id":{"$oid":"616d184962cb265db07d92cb"},
"lessson_image":null,
"status":1,
"is_deleted": 0,
"module_id":{"$oid":"616d17e462cb265db07d921f"},
"lessson_name":"Lesson 3"
}
I want to fetch details of all the courses user have enrolled and fetch all course’s modules and its lessons
My expected output should be like following —
[
{
//CourseDetail 1 Keys,
modules: [
{
//Module Details
lessons: [{
//lessons of this module
}]
},
{
//Module Details
lessons: [{
//lessons of this module
}]
}
]
},
{
//CourseDetail 2 Keys,
modules: [
{
//Module Details
lessons: [{
//lessons of this module
}]
},
{
//Module Details
lessons: [{
//lessons of this module
}]
}
]
}
]
Мой текущий запрос следующий: в настоящее время он группирует модули и их уроки вместе и привязывает их к одному объекту курса. Выбор модулей и уроков идеален в соответствии с моими требованиями, но массив курсов содержит только 1 отдельный объект, и в нем также содержится список всех модулей из других курсов.
Текущий Код Запроса
let courseDetails = await users.aggregate([
{
$match: { _id: mongoose.Types.ObjectId(user._id), }
},
{$unwind:"$enrolled_courses"},
{
$lookup: {
from: 'courses',
localField: "enrolled_courses.course_id",
foreignField: "_id",
as: "courseDetails"
}
},
{ $unwind: { path: "$courseDetails", preserveNullAndEmptyArrays: true}},
{
$lookup: {
from: "modules",
let: { currentCourseId: "$courseDetails._id"},
pipeline: [{
$match: {
$expr: {
$and: [
{ $eq: ["$course_id", "$currentCourseId"]},
{ $eq: ["$status", 1]},
{ $eq: ["$is_deleted", 0]},
{
$or: [
{ $eq: ["$is_always_available", true] },
{ $gte: ["$due_date", convertedDate]}
]
}
]
}
}
},
{
$project: {
_id: 1,
module_name: 1,
company_id: 1,
course_id: 1
}
}],
as: "moduleList"
}
},
{ $unwind: { path: "$moduleList", preserveNullAndEmptyArrays: true }},
{
$lookup: {
from: "lessons",
let: { curentModuleId: "$moduleList._id"},
pipeline: [{
$match: {
$expr: {
$and: [
{ $eq: ["$status", 1] },
{ $eq: ["$is_deleted", 0]},
{ $eq: ["$module_id", "$curentModuleId"]}
]
}
}
}, {
$project: {
_id: 1,
lessson_name: 1,
module_id: 1
}
}],
as: "moduleList.lessons"
}
},
{
$group: {
_id: "$_id",
course_id: { $first: "$enrolled_courses.course_id"},
course_name: { $first: "$courseDetails.course"},
completed_lessons: { $first: "$enrolled_courses.completed_lessons"},
current_lessons: { $first: "$enrolled_courses.current_lessons"},
completed: { $first: "$enrolled_courses.completed"},
enrolled_users_count: {
$first: "$courseDetails.enrolled_users"
},
modules: {
$push: "$moduleList"
}
}
},
{
$project: {
course_id: 1,
course_name: 1,
completed_lessons: 1,
current_lessons: 1,
completed: 1,
enrolled_users_count: {
$size: "$enrolled_users_count"
},
modules: 1
}
},
{
$group: {
_id: "$_id",
course_id: { $first: "$course_id"},
course_name: { $first: "$course_name"},
completed_lessons: { $first: "$completed_lessons"},
current_lessons: { $first: "$current_lessons"},
completed: { $first: "$completed"},
enrolled_users_count: { $first: "$enrolled_users_count"},
modules: { $first: "$modules"}
}
}
]);
Комментарии:
1. Четыре коллекции — это больше похоже на дизайн реляционной базы данных. Обычно количество коллекций намного меньше, чем количество таблиц в соответствующей реляционной базе данных. Не зная никаких подробностей, я бы предположил, что Курсы, Модули и Уроки смоделированы только в одной коллекции.
2. Согласно функциональности, у нас есть большое количество уроков, связанных с конкретным модулем, и большое количество модулей, связанных с конкретным курсом. Я создал несколько коллекций для этого, потому что мы также можем управлять всем этим по отдельности. Итак, я просто хочу получить все пользовательские курсы(доступные в коллекции enrolled_courses of users), а также все его модули и уроки за один раз.
3. если вы можете упростить данные, удалите дополнительные поля, сохраняйте только 1, вместо идентификаторов используйте числа, и проверьте, существуют ли идентификаторы в других коллекциях. Его уже так много просматривают. Я думаю, вам следует попробовать вложенные поисковые запросы, такие как поиск с помощью конвейера, в котором есть другой поиск с помощью конвейера внутри