MongoDB Tennis Match Schema - mongodb

What is the best way to structure a schema of a tennis match? A tennis match is best of 3 or best of 5 sets? A set is first to 6 games win by two. So if its is 5-5 you have to win by 2 (7-5). If its 6-6 you have to play a tiebreaker which is first to 7 points then you win the set. I want to create a schema for a match which will consist of 2 players that will reference their ids. I also need to keep track the scores of each set whether it is a best of 3 or best of 5 sets match. Will I have to create another schema for a set which will be an object with userId and games won, and tie breaker points?
Set = ({
player: {
ref: "User",
type: mongoose.Schema.Types.ObjectId,
},
games: {
type: Number,
required: false,
},
tiebreak: {
type: Number,
required: false,
},
});
Match = ({
players: [
{
ref: "User",
type: mongoose.Schema.Types.ObjectId,
},
],
setOne: [Set],
setTwo: [Set],
setThree: [Set],
setFour: [Set],
setFive: [Set]
});

Related

Design Followers and Followees Schema in MongoDB?

I want to design followers and followee(following) module for a social media application similar to instagram.
I've implemented following approach for the same
Users Schema
module.exports = mongoose.model('users', new Schema({
name: { type: String, default: null },
gender: { type: String, default: null, enum: ['male', 'female', 'others', null] },
email: { type: String, unique: true, sparse: true },
isBlocked: { type: Boolean, default: false },
isDeleted: { type: Boolean, default: false },
profileImage: { type: String, default: null },
isVerified: { type: Boolean, default: false },
}, {
versionKey: false,
timestamps: true
}));
Followers Schema
module.exports = mongoose.model('followers', new Schema({
followeeId: { type: ObjectId, required: true },
followerId: { type: ObjectId, required: true }
}, {
versionKey: false,
timestamps: true
}));
When using this approach if one user has 1 million followers then 1 million records will be created for that one user and if user followed back all the followers then count would be 2 million
So on average:
user#1 has 1 million followers/followees = 1 million records // total records: 1 Million
user#2 has 1 million followers/followees = 1 million records // total records: 2 Million
.
.
user#1000 has 1 million followers/followees = 1 million records // total records: 1 Billion
.
.
user#1,000,000 has 1 million followers/followees = 1 million records // total records: 1 Trillion
There would be more than trillions of records in a collection if I use this approach
So is it okay to generate records like this?
Or please suggest if there is any different approach to design this schema
Storing follower/following data in a list is such a wrong approach. If you have 1 million followers, you will have 1 million in the list of User table, making getting 1 user from the list extremely cumbersome. Also, you can't do pagination in that case.
Also, as you mentioned-
The size of ObjectId is 12 bytes and the limit per document is 16 MB.
So, after calculation, we can store about 1.4 million ObjectIds
(700,000 followers and 700,000 followees) and followers can easily
surpass the 2 million mark.
This is another reason why you shouldn't be storing follower/followee information in lists.
My advice-
Make a relationship table like this:
Follower_UserId | Following_UserId | Timestamp
So if Mel follows Pushpit then the entry would be like-
Mel_Id | Pushpit_Id | May 31
More examples-
Ash_Id | Pushpit_Id | May 30
Mel_Id | Ash_Id | May 31
Table size should be the least of your concern in this approach.
Data storage is cheap. The per-row size of this relationship table would be tiny. There are so many optimization techniques to handle large tables with many small-sized rows.
Good job finding the flaw in your own code. According to your schema, it will create too many records but there is another problem of querying the database at the time of finding followers of a user, it would be a little slow and you have to make a separate query as well!
So there must be another way. One more thing, it is always a best practice to name the model with a capital letter.
Here's what I would do with the same problem.
module.exports = mongoose.model('User', new Schema({
name: { type: String, default: null },
gender: { type: String, default: null, enum: ['male', 'female', 'others', null] },
email: { type: String, unique: true, sparse: true },
isBlocked: { type: Boolean, default: false },
isDeleted: { type: Boolean, default: false },
profileImage: { type: String, default: null },
isVerified: { type: Boolean, default: false },
followers: [{type: ObjectId, ref: "User", required: true}],
following: [{type: ObjectId, ref: "User", required: true}]
}, {
versionKey: false,
timestamps: true
}));
I would add 'followers' and 'following' field which contains arrays of ObjectIds of different users. So, each time someone follows a user, you would update the record of both the users - add the followee to the following field of the follower user and vice versa.
This approach would require doing two database update queries at the time someone follows someone. But it would save tonnes of resources and the time of querying later (you don't need to do a separate query for this).
Please let me know if you find any mistakes in this approach too.

How can I model my MongoDB database to allow me to easily add in new products & user interactions?

I am looking for the best way to model this scenario:
There is a ProductA model. Users can "like" or "dislike" ProductA documents. The documents are then added to an array in the User model called "likes" & "dislikes."
var UserSchema = new mongoose.Schema({
...,
likes: [{ type: mongoose.Schema.Types.ObjectId, ref: 'ProductA' }],
dislikes: [{ type: mongoose.Schema.Types.ObjectId, ref: 'ProductA' }],
...,
});
Now, I have realized that I want to add in a new Product: "ProductB." How do I restructure this database to keep this scalable and allow me to add new products? I am not sure what the best way to do this would be in MongoDB.
I believe my ideal scenario is the following psuedo-model:
var InteractionSchema= new mongoose.Schema({
product: // anonymous reference to an object
productType: //enum of which product it is
user: // user who made the interaction
interactionType: // like or dislike enum
});
I could not find any reference to how to handle anonymous references in MongoDB however. I would appreciate some advice
If I understand your requirement correctly, you can have three collections at a time:
products (contains all the products)
users (contains user information)
user_product_likes (contains user's like/dislike)
Respective schema can be,
UserInformationSchema :
{
name : {
type: String,
required: false
..
},
..
}
ProductSchema :
{
product_type : {
type: Integer,
},
...
}
InteractionSchema :
{
product_id : {
type: Integer
required: true
},
user_id : {
type: Integer
required: true
},
like : {
type: Boolean
required: false,
default:false
},
dislike : {
type: Booelan,
required: false,
default: false
}
}

Data modelling using mongoose for sports bet tracking application

I built a simple sports bet tracker application while I am learning the MERN stack. Users can track their sports bets and see various stats on their performance. It currently only supports tracking single bets (1 selection in bet) and I wish to add to ability to track multiple bets (>1 selections in bet). Each selection in a multiple bet will have the same data as a single bet eventDate, sport, event, selection odds etc. I'm just looking for some advice on the best way to add this in. Bet model currently is as follows
const betSchema = mongoose.Schema({
eventDate: {
type: Date
},
sport: {
type: String
},
event: {
type: String
},
market: {
type: String
},
selection: {
type: String
},
odds: {
type: Number
},
result: {
type: String,
default: 'Pending'
},
stake: {
type: Number
},
owner: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'User'
}
}, {
timestamps: true
})
Going forward a bet can have one selection or many in it so I was thinking this should become an array. If it has one selection the odds for the bet will be the odds of that selection but if it has multiple selections in it the odds of the bet will be the odds of the selections multiplied. If one selection in a multiple bet loses the bet is a loss. I was thinking something like the following setup but I'm not sure as I don't have much database experience any help who'd be appreciated.
const betSchema = mongoose.Schema({
selections: [{
sport: {
type: String
},
event: {
type: String
},
eventDate: {
type: Date
},
market: {
type: String
},
selection: {
type: String
},
result: {
type: String
},
odds: {
type: Number
},
}],
odds: {
type: Number
},
stake: {
type: Number
},
result: {
type: String,
default: 'Pending'
},
owner: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'User'
}
}, {
timestamps: true
})
I went with the Schema shown in the question, not sure if it's the best solution but it works for what I am trying to build.

How join two collections in MongoDB using node js

I have searched for join two collection in MongoDB. I found populate. But it is not working for my scenario. I am using mongoose in node js. My schema are like below.
const CoordinateSchema = new mongoose.Schema({
activationId: {
type: mongoose.Schema.ObjectId,
ref: 'Activation'
},
mac: {
type: mongoose.SchemaTypes.String,
required: true,
set: toLower
},
t: { type: Date },
userId: {
type: mongoose.Schema.ObjectId,
ref: 'User'
}
});
const UserSchema = new mongoose.Schema({
email: {
type: mongoose.SchemaTypes.String,
required: true,
//unique: true,
set: toLower
},
mac: {
type: mongoose.SchemaTypes.String,
required: true,
unique: true,
set: toLower,
index: true
},
dob: {
type: mongoose.SchemaTypes.Date,
},
gender: { type: mongoose.SchemaTypes.String, set: toLower },
activations: [{
activationId: {
type: mongoose.Schema.ObjectId,
ref: 'Activation'
},
userType: { type: mongoose.SchemaTypes.String, set: toLower },
_id: false
}]
}
i have thousands of records for single activation in coordinates collection.
My query query requires to filter distinct mac from coordinates collection which matches userType in user collection.
If i use populate method & then apply filter on that it won't restrict fetching record count because of it query is taking so much time because it will return thousands of records.
I want to fetch only coordinates which match userType in user collection.
So far i haven't found any efficient method to join two collection & apply where condition on it.
I want to know efficient method to join two collection in mongodb & apply where condition on both collections.

Modelling many-to-many relationships in MongoDB

I am having difficulty coming up with schemas for a school app.
In particular, I am trying to model the relationship between the different kinds of users (e.g. instructors, teaching assistants, and students) with the courses and tutorials that they belong to.
Here are my requirements:
each course will have one to many tutorials;
each course will be taught by one to many instructors;
each course will have one to many students;
each tutorial will have one to many teaching assistants;
each instructor will teach one to many courses;
each teaching assistant may have one to many tutorials in one to many course;
each student will be enrolled in one to many courses;
each student may belong to one tutorial in the course that they are enrolled in;
So far, the following are my schemas for the user, course, and tutorial collections.
var CourseSchema = new mongoose.Schema({
name: { type: String, required: true },
code: { type: String, required: true },
tutorials: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Tutorial' }], // 1
instructors: [{ type: mongoose.Schema.Types.ObjectId, ref: 'User' }], // 2
students: [{ type: mongoose.Schema.Types.ObjectId, ref: 'User' }] // 3
});
var TutorialSchema = new mongoose.Schema({
number: { type: String, required: true },
teachingAsst: [{ type: mongoose.Schema.Types.ObjectId, ref: 'User' }] // 4
});
var UserSchema = new mongoose.Schema({
email: { type: String, lowercase: true },
password: String,
name: {
first: { type: String, lowercase: true },
last: { type: String, lowercase: true }
},
roles: [String] // instrutor, teachingAsst, student
};
The problem lies with my requirements 5 to 8 -- which is more so the relationship from the User to the other models. What could be a good way to model these relationships?
One way, I thought of doing it e.g. req 5 was to add a field to the User schema
instructor: {
courses: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Course' }]
}
But the problem happens when I do e.g. req 6. similarly because it will complicate the queries (e.g. "find all the tutorials in a course that the user is a teaching assistant in").
teachingAsst: {
courses: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Course' }]
tutorials: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Tutorial' }]
}
In your case, Design is many to many relations. So you have two approach for your problem.
Reference Document
Embedded Document
Embedded approach will have duplicate data which is difficult to update and delete where as the read operation will be much efficient due to single query.
In case of the Reference Approach, your data will be demoralized. So, update and delete operation will be easy where as the read operation will have multiple hits on the database.
So, based on the your application requirement you should have to decide the appropriate approach.