I am building a MERN (with Next.js) stack Learning Management System. Currently, I have built the front-end for the Assignments that lists the assignments for that course. For example, if I am logged in, I will see all my assignments for PHIL 204 course if I go to test.com/courses/PHIL204/Assignments. Now, in this table, there is a column that says "Status" which tells if the assignment has been started, submitted, or graded (only 3 values). My question is, how do I store/calculate this value? I have Students and Assignments as two collections (out of many) in my DB. My DB is still in dev, so I can easily follow your suggestions. I don't suppose the Assignments col should have a "status" field because that would show the same for all students that have that assignment. If you need any code from me, I can provide that. I am seeking help mostly for the logic of what/how to store if a student has started, submitted, or graded(by the prof) that assignment.
Any help would be greatly appreciated. Thank you very much.
Actually, GitHub Copilot suggested me that in the Students schema I have something like this:
const studentSchema = mongoose.Schema({
studentFirstName : {type : String, required: true},
studentLastName : {type : String, required: true},
studentEmail : {type : String, required: true},
studentClass : {type : String},
studentAssignments : [{
assignmentId : {type : Schema.ObjectId, ref: 'Assignments'},
assignmentGrade : {type : String, enum : ["A","A-","B+","B","B-","C+","C","C-","D+","D","D-","F"]},
assignmentStatus : {type : String, enum : ["Not Started", "Started", "Submitted", "Returned"]},
assignmentRemarks : {type : String},
assignmentCompeletedDate : {type : Date},
}],
studentTestQuizzes : [{
testQuizId : {type : Schema.ObjectId, ref: 'TestQuizzes'},
testQuizGrade : {type : String, enum : ["A","A-","B+","B","B-","C+","C","C-","D+","D","D-","F"]},
testQuizStatus : {type : String, enum : ["Not Started", "Submitted", "Returned"]},
testQuizRemarks : {type : String},
testQuizCompletedDate : {type : Date},
}],
studentAnnouncements : [{
announcementId : {type : Schema.ObjectId, ref: 'Announcements'},
announcementStatus : {type : String, enum : ["Read", "Not Read"]},
}],
// we need a courseId to link the student to a course
}, { collection: 'Students' });
This should work. I will update this thread, if it does not work or if I need to do some more work.
Related
I am Newbie working on a social networking site & using MongoDB as Database. Can you please assist me in What approach should I follow in Designing Database?
My Requirements and Objective for Designing Database
The Most common queries are gonna be related to the user interactions like what topics had user followed, how the user interacted with the post, how many times was the post on the newsfeed of the user and at what time for further showing him that post after some time.
My objective is not to calculate Number of likes, number of comments often but what they query I want to get quickly to keep the performance up is just that Is the user interested in the post by checking did he liked it or not.
So should I:
Make Different collections for storing likes, comments, etc containing the reference field of Posts collection & User Collection for the user who interacted.
Ex:
db.like.find()
{_id: , user_id: "the user_id of the user", post_id: [ALL THE POST_ID's USER LIKED]}
db.comment.find()
{_id: , user_id: "the user_id of the user", comments: [{_id: , post_id: , replied_to: [ LIST OF USERS REPLIED IN THE COMMENT], votes: [ LIST OF ALL THE VOTERS] , timestamp: }] }
Making a List of Embedded Documents in a collection with a user_id, post_id, and any interaction he made with the post.
So one document per user. And one embedded document in the list per post interaction.
Ex:
db.all_the_interactions.find()
{_id: , user: ObjectId("1782..."), username: "Mark Alberto" interactions:[
{post_id: ObjectId("222..."), liked: True, "Comment": ["Hello"], timestamp},
{post_id: ObjectId("672..."), liked: False, "Comment": [], timestamp}
]}
{_id: , user: ObjectId("4355..."), username: "Himesh Reshamiya" interactions:[
{post_id: ObjectId("224..."), liked: True, "Comment": [], timestamp},
{post_id: ObjectId("562..."), liked: False, "Comment": ["Nice"], timestamp}
]}
Making an Entire Collection for a user where all his interactions will be stored.{_id, post_id, liked(if he liked), (list of comments that this particular user made(if any)), time of comment(if any comment made)}.
Ex:
db.user_name.find()
{_id, post_id: 432.., liked: True, Comment: ['StackOverflow']}
{_id, post_id: 433.., liked: True, Comment: []}
Storing all the users who liked the post in the list in the posts-collection itself & a list of embedded documents for comments.
Ex:
db.post.find()
{
"_id" : ObjectId("62f7930758bcf38e4f920e87"),
"username" : "Akshat Bafna",
"fact" : "clone()\r\nCreate a copy of the current queryset.clone()\r\nCreate a copy of the current queryset.",
"background" : "mongodb-logo-vector-2022.png",
"creation_date_time" : "08/13/2022, 17:33:19",
"topic": "MongoDB",
"liked":[ALL THE USER_ID's LIKED THIS POST],
"comments":[{_id: , user_id: ,"replied_to": [ LIST OF USERS REPLIED IN THE COMMENT], votes: [ LIST OF ALL THE VOTERS] , timestamp: } ]
}
Store all the Posts user liked in user collection as a list of posts_id
{ "_id" : ObjectId("62dee9d49974d78430d99af6"),
"user_type" : "initiatives",
"username" : "Anand Mahindra",
"password" : "99fb2f48c6af4761f904fc85f967445665445d40b1f44ec3a9c1fa319", "email" :
"mahindraanand#gmail.co",
"last_login" : "N/A",
"last_logout" : "N/A",
"post_liked": [ALL THE POST_ID's USER LIKED],
"comments": [{_id: , post_id: ,"replied_to": [ LIST OF USERS REPLIED IN THE COMMENT], votes: [ LIST OF ALL THE VOTERS] , timestamp: }] }
As MongoDB is a Dynamic Database what should be the right criteria for designing a database for best performance?
The best way to design a schema for that purpose will be using the combination of second and third method if you require all the data that's going to be stored in a document. The document will look like this:
{ "_id" : ObjectId("6323c511a78cf05ddc91d868"), "userReference" : ObjectId("62c1f108449a868937fgg355"), "username" : "Akshat Bafna", "postId" : ObjectId("62f563ed918ea74846d3aa95"), "liked" : false, "lighten" : false, "timesViewed" : 1, "points" : 10, "timeList" : [ "16/09/2022 06:06:33" ] }
{ "_id" : ObjectId("6323c511a78cf05ddc91d869"), "userReference" : ObjectId("62c1f108449a868937edfs7f"), "username" : "Joe Bidden", "postId" : ObjectId("62f7785eb90971094fffe9d8"), "liked" : false, "lighten" : false, "timesViewed" : 1, "points" : 10, "timeList" : [ "16/09/2022 06:06:33" ] }
{ "_id" : ObjectId("6323c511a78cf05ddc91d86a"), "userReference" : ObjectId("62c1f108449a868937fgg355"), "username" : "Akshat Bafna", "postId" : ObjectId("62f7911c4191afb7b90641d6"), "liked" : false, "lighten" : false, "timesViewed" : 1, "points" : 10, "timeList" : [ "16/09/2022 06:06:33" ] }
Inshort Why I prefer this?
Because ever growing arrays with embedded documents will be a performance issue.
Expensive writes & updates.
Document size limit on 16mb in mongodb as ever-growing documents becoz of ever growing arrays will never stop it will be an issue.
Index creation will get expensive.
For more information, see: Why shouldn't I embed large arrays in my documents?.
Also you might have to add some data redundancy for better performance, create ttl indexes with the single user_interactions collection or when using a separate collection for individual user capped collections can be used if it does not violate your requirements.
I'm having issues querying data with orderByChild. I would like to query all tasks where provided userID matches any approver id. Task ID is autogenerated so I need to flatten this structure somehow.
Each task has two approvers, and each approver has status, timestamp, id.
Any idea on how to flatten it so I can take advantage of orderByChild?
Tasks:{
"df234dgkjsf234" : {
"approvers" : {
"4U1D23dfsdf23e" : {
"id" : "4U1DWf95rJvgfAwDYs7m",
"status" : "pending",
"timestamp" : "pending"
},
"sdf32fdsf34sdg3" : {
"id" : "FXRkK22TjyxKV6z4UkrU",
"status" : "pending",
"timestamp" : "pending"
}
},
"reason" : "test",
"requester" : "4U1DWf95rJvgfAwDYs7m",
"requesterName" : "Dana Mayers",
"status" : "pending",
"tagetValue" : "QT1IkGHS3mmalyXqdCuD",
"taskName" : "Title Change",
"timestamp" : 1644773238,
"value" : "New Title"
},
"d4S34FSAdsf43FM" : {
...
}
}
I want to make ideally one query to get this data as opposed to querying by Approver1 and then by Approver2
Tasks:{
"df234dgkjsf234" : {
"Approver1" : "4U1DWf95rJvgfAwDYs7m",
"Approver1status" : "pending",
"Approver1timestamp" : "pending"
"Approver2" : "FXRkK22TjyxKV6z4UkrU",
"Approver2status" : "pending",
"Approver2timestamp" : "pending",
"reason" : "test",
"requester" : "4U1DWf95rJvgfAwDYs7m",
"requesterName" : "Dana Mayers",
"status" : "pending",
"tagetValue" : "QT1IkGHS3mmalyXqdCuD",
"taskName" : "Title Change",
"timestamp" : 1644773238,
"value" : "New Title"
},
"d4S34FSAdsf43FM" : {
...
}
}
There is no way to do this with one query, since you're looking for two separate values. The closest you can get is by doing two separate queries on (4Approver1 and Approver2 in) the second data structure, and then merging the results in your application code.
The alternative is to add a secondary data structure, where you map from the user ID back to the tasks they're allowed to approve:
UserTasks: {
"4U1D23dfsdf23e": {
"df234dgkjsf234": true,
"d4S34FSAdsf43FM": true
},
"sdf32fdsf34sdg3": {
"df234dgkjsf234": true
}
}
With such an additional structure you can easily find the tasks for a specific UID, and then load the task details for each.
For more on this, I recommend also reading:
Many to Many relationship in Firebase
Firebase query if child of child contains a value
Firebase Query Double Nested
I have basic project on Firebase, AngularJS.
{
"users" : {
"X3IuXTMi9RgOLMKBoqPJtB1JGGQ2" : {
"profile" : {
"firstName" : "test",
"lastName" : "5",
"username" : "test5"
}
},
"poPg2BfHA1gq3qtXNLbuw4X2Zt23" : {
"profile" : {
"firstName" : "test3",
"lastName" : "asdfg",
"username" : "test3"
}
}
}
}
i want to add users by username basically. when type username on alertprompt(ionic) and click add, it will find target username and get uid on its parent. and it will write data on "users/$targetuid/friendrequests/$senderuid"
my closest search result was that: Retrieve data of child of unknown parent ID - Firebase
but i cant use any .ref codes;
Cannot read property 'ref' of undefined
i just can use FirebaseObjectObservable, what im i doing wrong ? why cant i use
firebase.database().ref
or any like this code based on .ref command?
basically cant do anything here: https://firebase.google.com/docs/database/web/read-and-write
im am sort of new on coding, so if its easy or funny dont laugh much. thanks for reading.
I can see two solutions here:
1) Create a usernameToUserid map: on firebase create a new resource usernameToUserid, ike below:
{
"users" : {
"X3IuXTMi9RgOLMKBoqPJtB1JGGQ2" : {
"profile" : {
"firstName" : "test",
"lastName" : "5",
"username" : "test5"
}
},
"poPg2BfHA1gq3qtXNLbuw4X2Zt23" : {
"profile" : {
"firstName" : "test3",
"lastName" : "asdfg",
"username" : "test3"
}
}
},
"usernameToUserid: {
"test5": "X3IuXTMi9RgOLMKBoqPJtB1JGGQ2",
"test3": "poPg2BfHA1gq3qtXNLbuw4X2Zt23"
}
}
This way you can retrieve the userId and then the user profile with the username.
2) Retrieve all users and search locally for username, terrible idea.
I'm trying to bind (two ways bind) some field of my form with data provided by my view model.
When I bind a simple string, it works perfectly. But when I try to bind a form field to an array field inside my viewmodel, modifications are not considered by the view model.
This is my model
Ext.define('Front.model.User', {
extend : 'Ext.data.Model',
fields : [{
name : 'id',
type : 'int'
}, {
name : 'name',
type : 'string'
}, {
name : 'email',
type : 'string'
}, {
name : 'last_connection',
type : 'date',
dateFormat : 'Y-m-d H:i:s'
}, {
name : 'birth',
type : 'date',
dateFormat : 'Y-m-d H:i:s'
}, {
name : 'schedule',
type : 'auto'
}]
});
This is my ViewModel
Ext.define('Front.view.user.SheetModel', {
extend : 'Ext.app.ViewModel',
alias : 'viewmodel.sheet',
requires : ['Front.model.User'],
data : {
currentUser:null
},
model : 'Front.model.User'
});
This is my Form
Ext.define('Front.view.user.Sheet', {
extend : 'Ext.form.Panel',
requires : ['Front.view.user.SheetController'],
controller : 'sheet',
viewModel : {
type : 'sheet'
},
config : {
currentUser : null
}, {
xtype : 'textfield',
fieldLabel : 'De',
name : 'morningstarttest',
width : 60,
bind : {
value : '{currentUser.schedule.lundi.am.start}'
}
}
});
The bind displays the correct value the first time but doesn't update if I change the value.
The 'schedule' field in a model is an array.
Any ideas how I could solve this problem?
How can your code know which item in the array to bind against? You'd need to do something like:
{currentUser.schedule[0].lundi.am.start}
In order to specify an array index. I can't remember offhand if you can do this, and that's because this just feels like a bad idea. I'd suggest rethinking what you're attempting to do. Rather than have schedule as a field on your model, look into associations.
In my Firebase I have a entry called 'status' which has some records as 'active' and others as 'inactive'. I am trying to return all records that have the status of 'active'. I am doing the following statement.
new Firebase($rootScope.constants.firebase)
.startAt('active')
.endAt('active')
.once('value', function(snap){
console.log(snap.val());
});
However this is returning NULL.
I am adding data to firebase in the following way:
$firebase(ref).$add({
date: Firebase.ServerValue.TIMESTAMP,
status: 'active'
})
My firebase data looks like the following:
{ "-JSex4_si4a2ZMOLcEuj" : {
"date" : 1406248704619,
"status" : "active",
},
"-JShWyGQzDtAl-F8EkOI" : {
"date" : 1406291928576,
"status" : "active",
}}
Please can someone explain why I am getting NULL and how to get all records with this 'active' status?