Context: I need some tips to model the parts shaded in blue in the entity diagram shown above.
The Entities User, Channel, Course and Topic and their relations are already modelled in the database by collections of the same name.
The are modelled in the following simple manner:
- User contains an array of references to the Courses.
- A Course contains an array of references to the Topics
- A Topic cotntains an array of references to the Channels
Question: How can I now model the new many to many has Notification Settings For Relationship between
- The User and the Channel
- The User and the Topic
- The User and the Course
as shown in the diagram.
Note that this relation also contains an attribute called s1, s2, s3 for simplicity’s sake.
The reason for asking this question is, that I have a Query that a User does everytime when he/she uses the application.
Everytime a Course is fetched, I want to fetch :
- The Topic’s in the Course
- the value of the attribute s2 for every Topic from step 1
- The Channels connected to each Topic from step 1
- The s3 attribute for every Channel in step 3
AND I want to send the result in the following manner to the Front end:
Basically, Channels that belong to particular topic are put in an array and sent with the respective topics object. Example below for illustrative purpose
{
First 2 properties are the Course Properties
"_id": "647666fb1296a965aa631cfa",
"name": "Front end fundamentals",
"s1": true,
"topics": [
{
"topicId": "647856b01296a965aa6321cd",
"s2": true,
"_id": "647856b01296a965aa6321cd",
"name": "UX Design",
"courseId": "647666fb1296a965aa631cfa",
"userId": "64766648ef43feb4849b2cea",
"channels": [
{
"topicId": "647856b01296a965aa6321cd",
"channelId": "647856cd1296a965aa63221e",
"s3": true,
"_id": "647856cd1296a965aa63221e",
"name": "Introduction",
"description": "",
"courseId": "647666fb1296a965aa631cfa",
"userId": "64766648ef43feb4849b2cea",
},
{
"topicId": "647856b01296a965aa6321cd",
"channelId": "64785a2a1de1c55ba02df099",
"s3": true,
"_id": "64785a2a1de1c55ba02df099",
"name": "Lecture 1",
"description": "",
"courseId": "647666fb1296a965aa631cfa",
"userId": "64766648ef43feb4849b2cea",
},
{
"topicId": "647856b01296a965aa6321cd",
"channelId": "43534tg4566trretwert23",
"s3": true,
"_id": "64785a2a1de1c55ba02df099",
"name": "Lecture 1",
"description": "",
"courseId": "647666fb1296a965aa631cfa",
"userId": "64766648ef43feb4849b2cea",
},
{
"topicId": "647856b01296a965aa6321cd",
"channelId": "64785a2a1de1c5dasfrewtdfsg35",
"s3": true,
"_id": "64785a2a1de1c55ba02df099",
"name": "Lecture 1",
"description": "",
"courseId": "647666fb1296a965aa631cfa",
"userId": "64766648ef43feb4849b2cea",
},
],
"createdAt": "2023-06-01T08:28:32.154Z",
"updatedAt": "2023-06-01T08:28:32.154Z",
"__v": 14
},
{
"topicId": "647ef264e2c03f930e3b3854",
"s2": true,
"_id": "647856b01296a965aa6321cd",
"name": "UX Design",
"courseId": "647666fb1296a965aa631cfa",
"userId": "64766648ef43feb4849b2cea",
"channels": [
{
"topicId": "647ef264e2c03f930e3b3854",
"channelId": "7893214hjbf801346y",
"s3": true,
"_id": "dasdf78032343nkjhkjnkj234",
"name": "test 2:35",
"description": "Teaching about xAPI Notifications once again",
"courseId": "647666fb1296a965aa631cfa",
"userId": "64766648ef43feb4849b2cea",
},
{
"topicId": "647ef264e2c03f930e3b3854",
"channelId": "23574934057934057",
"s3": true,
"_id": "648705fdf5cf921815ae5960",
"name": "test 2:35",
"description": "Teaching about xAPI Notifications once again",
"courseId": "647666fb1296a965aa631cfa",
"userId": "64766648ef43feb4849b2cea",
}
],
}
}
Possible Solution
This is the solution that I have come up with and it is working but I am not sure if this is the best possible way to model it.
I introduced a new Collection called Notification Settings in my database.
It has the following shape:
const BlockingNotifications = new Schema({
userId: {
type: Schema.Types.ObjectId,
ref: "user",
required: true,
index: true,
},
courseId: {
type: Schema.Types.ObjectId,
required: true,
ref: "course",
index: true,
},
s1: { type: Boolean },
topics: [
{
topicId: {
type: Schema.Types.ObjectId,
ref: "topic",
},
s2 : { type: Boolean },
},
],
channels: [
{
topicId: {
type: Schema.Types.ObjectId,
ref: "topic",
},
channelId: {
type: Schema.Types.ObjectId,
ref: "channel",
},
s3 :{ type: Boolean },
}
],
})
A particular document of the above collection, would for a particular Course and a User, contain all the Topics, and Channels of the Course along with their respective attributes (s1, s2, s3) .
When I make the query for a particular course, I first look for the document of the above collection with the userId
equal to the User making the query.
and using a aggregation pipeline, I perform a $lookup
on all the Topics and Channels.
Then once again using aggregation I arrange the channels into the respective topic to which they belong. I do this using the $map
Operator. To figure out which channel belongs in which topic. The result looks like the first code snippet.
I would like to know if this is the best possible way to model this data and Query this data.
If needed I can also post the aggregation pipeline if interested.