MongoDb: In a many to many relation, when does it make sense to make the ids of both models in the definition of the other model - mongodb

I have this relation:
User has many courses
I have implemented it by integrating the user_id in the definition of the Course model:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
//Create Schema
const CourseSchema = new Schema({
user: {
//This will associate the user by his id
type: Schema.Types.ObjectId,
ref: "users",
},
date: {
type: Date,
default: Date.now,
},
});
module.exports = Course = mongoose.model("course", CourseSchema);
This way, if I want to get the courses created by a user X, I just use his id and look it up in the courses documents.
I thought with a big data base, this operation may be costly.
So I should add the course_id, to an array property called courses in the User model:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const UserSchema = new Schema({
courses: [
{
type: Schema.Types.ObjectId,
ref: "course",
},
],
});
module.exports = User = mongoose.model("users", UserSchema);
This way, I can simply populate that array with the .populate operation, instead of going with the appraoach mentioned above.
I would like to know if my way of thinking makes sense.
And whether there other reasons for me to add the course_id, to courses property in the User model.

both approach is correctly I have seen both methods that uses
but when you want to using populate, you should update two collections(users and courses) when you want to insert a new Course, so you should use transaction because if one was updated and the other did not(An error occurred) rollback be done
the first thing to understand about mongoose population is that it is not magic, but just a convenience method that allows you to retrieve related information without doing it all yourself
if user id be index in couresSchema you can find() all courses very fast,
but the generally recommendation is to consider the data usage patterns of your application and choose what is best

Related

Query db without certain elements inside an array

I set up a small database using a model and 2 schemas.
The model goes as follows:
const userSchema = new mongoose.Schema({
friendsRequests: [friendRequestSchema],
//other credentials that are not important//
});
And the friendRequestSchema:
const friendRequestSchema = new mongoose.Schema({
from: { type: Schema.Types.ObjectId, ref: "User" },
to: { type: Schema.Types.ObjectId, ref: "User" },
});
Basically friendsRequests is an array consisting of who requested to add the user to the friends list (which is the from property) and whom the user wants to add to their friends list (which is the to property).
For the query, I am trying to sort out how to send a response without containing the users that are inside the user's friendsRequests array.
If i do this :
const recFriends = await User.findOne({ _id: req.user }).select(
"friendsRequests"
);
i will get back the array with objects containing either sent or received requests. Now i want to query again the User model and have it not return elements from this array. How would i go about doing that?

How to create an Insert trigger in mongodb atlas?

I am new to NoSQL/MongoDB and I need to write a trigger on insert event on one of the collection in my database as follow: Database Name: GiftShop Collection Name: Gifts
Gifts Schema is as Follows:-
const mongoose = require("mongoose");
const userModel = require('./userModel');
const imageModel = require('./imageModel');
const giftSchema = mongoose.Schema({
name: String,
availableQuantity: Number,
price: Number,
Seller: {type: mongoose.Schema.Types.ObjectId,ref: 'UserModel'},
imageName: {type: mongoose.Schema.Types.ObjectId,ref: 'ImageModel'},
deliveryInDays: Number,category: [{type: String, ref: 'CategoryModel'}]
}, {collection: "gifts"});
module.exports = giftSchema;
I have another collection named as a notification. I want to create a trigger as such, as soon as the new gift gets inserted in gift collection the notification collection must get populated with the information having:
gift id,
seller id,
an array of buyer id.
the schema for notification is as follows:
const mongoose = require("mongoose");
const notificationSchema = mongoose.Schema({
seller: { type: mongoose.Schema.Types.ObjectId,ref: 'UserModel'},
buyer: [{type: mongoose.Schema.Types.ObjectId,ref: 'UserModel'}],
newGift: {type: mongoose.Schema.Types.ObjectId,ref: 'GiftModel'}
}, {collection: "notifications"});
module.exports = notificationSchema;
following is the function I wrote in MongoDB atlas but it has many issues with it:
exports = function (changeEvent) {
const {fullDocument} = changeEvent;
const {buyer, seller, newGift} = fullDocument;
const collection = context.services.get("Cluster0").db("test").collection("notification");
return collection.insertOne({buyer, seller, newGift})};
the setup I did on MongoDB atlas to create my trigger:
I am inserting a new gift via MongoDB compass which is connected to my MongoDB atlas but my notification collection is not getting populated with the data mentioned in the schema of notification. Where am I going wrong? and what is the correct way to write the trigger according to my requirement? Thank you.
There are some pointers for debugging stitch functions here, you should be able to follow those to determine if the issue is with your function or the trigger.

class registration schema recommendation

I am trying to design a database of a class registration relationship. Is this the best way for this situation?
Registration schema
const mongoose = require("mongoose");
//Course Schema
//Faculty can add courses to the DB
const registrationSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
courseID: { type: mongoose.Schema.Types.ObjectId, ref: "Course" },
studentID:{ type: mongoose.Schema.Types.ObjectId, ref: "User" }
});
module.exports = mongoose.model("Registration", registrationSchema);
Instead of a seperate registration collection, why not try modelling using 'Two-way embedding' approach? refer
So your Course collection will have array of students reference and Student collection will have an array of courses reference, for easy retrieval.

MongoDB schema design(mongoose): User, Event, several members and moderators by event

I have an app with a mongoDB. A user can create events. An Event has one or more members, and one or more moderators as well. I am trying to decide which is the best schema for this app. I'm using mongoose. I tried to think the "mongo" way but I ended up with a highly relational schema.
var mongoose=require('mongoose');
//user log in using facebook, what should I store here?
var userSchema = new mongoose.Schema({
user data:......
});
var eventSchema= new mongoose.Schema({
name:String ,
description:String,
type:String,
user_id:Number,
created_at: {type:Date,default:Date.now}
});
var eventParticipantsSchema=new mongoose.Schema({
users:Array,
event_id:Number
});
var moderatorParticipantSchema=new mongoose.Schema({
users:Array,
event_id:Number
});
Which would be a more NoSQL schema?. I read about using the User as the main object containing array of events and within the events array a prop for an array of moderators and another prop of an array of members
Users{
events_array:{
moderators_array:
members_array:
}
}
but I read it was not recommended if you have to push into the contained arrays too many times. So, what would be a nice design for this app?.....Thank you very much....

Relations in NoSql using mongoDB and Mongoose

Ok, im comming from an SQL background and I am just getting my hands dirty using MongoDB and Mongoose.
I have two simple models:
CAR:
let mongoose = require('mongoose');
let carsSchema = new mongoose.Schema({
brand: String,
specfifications: [String],
image: String
});
module.exports = mongoose.model('Car', carSchema);
Driver
let mongoose = require('mongoose');
let Schema = mongoose.Schema;
let driverSchema = new mongoose.Schema({
name: String,
cars: [{ type: Schema.Types.ObjectId, ref: 'Car' }]
});
module.exports = mongoose.model('Driver', driverSchema);
From what I can understand, this seems to be a proper way of handling a one-to-many-relationship where one car can be used by many drivers.
Now I need to add a class called Races which will be used for saving the results for spacific driver in a specific car.
Thinking in SQL I would do something like this:
let mongoose = require('mongoose');
let raceSchema = new mongoose.Schema({
totaltime: String,
laptime: String,
driver: { type: Schema.Types.ObjectId, ref: 'Driver' },
car: { type: Schema.Types.ObjectId, ref: 'Car' }
});
module.exports = mongoose.model('Race', raceSchema);
Would you consider this to be to correct approach in NoSql or am I forcing my SQL-way of thinking into NoSQL?
the answer is it depends
MongoDB or NoSQL theory says if all related data are in one document, then your query will run faster as they will be stored together. So, in most cases we would prefer one single model for both Car and Driver
If you do not query car and drivers together in most of your queries (chances for which would be rare), then what you did is also correct.
Also, MongoDB has a limitation on size of document i.e. 16 MB if you think the cost of storing them together can go beyond 16MB then what you did is correct. However, there is an alternate solution i.e. GridFS which stores the documents into chunks and overcomes this limitation