Database modeling with mean.js and mongoose - mongodb

I am classical developer who is normally developing relational DBs form my web applications.
I want to learn the new way and build an application with mean.js and mongoDB. I used yo generator from the meanjs.org to get started.
When I model my data I always fall back into the classic relational modeling. And I think this is not what the “new way” of app building is all about.
So my question is: What is he best practice to model my data model sample?
My learning sample is an app in which you have a specific given list of music albums (like best 50 Jazz albums of all times) and the user checks in and rate the music.
I have a CRUD module for adding and editing albums the user should listen to. This ends in an ordered list of albums.
I have a CRUD module for users, generated by the yo generator.
A user now can see the list and mark the albums which he already heard. He should be able to give a rating and a comment.
So the question is: where to store the user listenTo info? In the relational world I would introduce a new foreign key table which has a relation from user to album and model the properties like rating and comment in the foreign key table. I don’t think this is how things should work in mongo DB world, does it?
I could add the user listenTo information to each album. I would have a list of users and comments on each album. Then, I need to ensure that if the list is requested, only the information of the current user is present. So I would have to filter on property on a sub-sub-document. Feels strange.
Or, I could copy the album list for each newly created user but then I need to write code that changes the user’s object when I edit the original list.
What would you recommend?

When I think of Data Modeling, I break things down into the following relationships:
1 <--> 1
1 <--> Few/Many (A finite number, say a list of user's phone numbers)
1 <--> Very Many
The general rule of thumb with MongoDB is you should embed wherever possible. So for 1 <--> 1 and 1 <--> Few/Many if the document size is something small, you should embed the collection inside the user document.
It's important to think about the use case here. If we want to track all songs that the user likes or listens to, this could potentially be hundreds or thousands, so we probably want to store this information in a separate collection and contain an indexed reference to the user there.
In the case of tracking if a user listens to the song, I would probably structure it like this in your use case:
{
_id: ObjectID, // The identifier of the document
user_id: ObjectID, // The user who listened to the song
song_id: ObjectID, // The id of the song
count: number, // The number of times the user listened
rating: number, // The number of stars the user rated the song
favorite: boolean, // If the user marked the song as a favorite
last_listened: Date // The last time the user listened
}
With an index on { user_id: 1, song_id: 1 }.
Here is a really good reference on how to approach your problem:
https://docs.mongodb.com/manual/applications/data-models-relationships/

Related

How to organize FireStore Collections and Documents based on app similar to BlaBlaCar rides

It's my first time working with FireStore. I'm working on a ridesharing app with Flutter that uses Firebase Auth where users can create trips and offer rides similarly to BlaBlaCar, where other users can send requests to join a ride. I’m having difficulty not only deciding the potential collections and paths to use, but also how to even structure it.
For simplicity at this stage, I want any user to be able to see all trips created, but when they go to their “My Rides” page, they will only see the rides that they’ve participated in. I would be grateful for any kind of feedback.
Here are the options I’ve considered:
Two collections, “Users” and “Trips”. The path would look something like this:
users/uid and trips/tripsId with a created_by field
One collection of “Users” and a sub-collection of “Trips". The path seems to make more sense to me, which would be users/uid/trips/tripId but then I don't know how other users could access all the rides on their home feed.
I'm inclined to go with the first option of two collections. Also very open to any other suggestions or help. Thanks.
I want any user to be able to see all trips created, but when they go
to their “My Rides” page, they will only see the rides that they’ve
participated in
I make the assumption that participating in a ride is either being the author or being a passenger of the ride.
I would go for 2 collections: one for users and one for trips. In a trip document you add two fields:
createdBy with the uid of the creator
participants: an Array where you store the author's uid and all the other participants uids (passengers)
This way you can easily query for:
All the rides
All the rides created by a user
All the rides for which a user is a participant, using arrayContains.
(Regarding the limit of 1 MiB for the maximum size for a document I guess this is not a problem because the number of passengers of a ride shouldn't be so huge that the Array fields size makes the document larger than 1 Mib!)
Note that the second approach with subcollections could also be used since you can query with collections group queries but, based on the elements in your question, I don't see any technical advantage.

Mongodb Storing Friends Relationship

I am using MongoDb for one of the mobile app that we are developing. It has a feature of sync contacts.
I wanted to know the ideal way of storing the relationships(friends relationship and not RDBMS kind of relationship) in mongodb. I want to know the architecture for the same.
I have thought of the following user collection structure:
{
_id: ObjectID(abc),
name: "abc",
contacts: ["def", "ghi"]
}
In the above collection I am considering "def" and "ghi" as object ids of friends of user abc. Is this the correct way of doing it or can someone suggest me a better and right way that they might have implemented?
All I am concerned about is I should not get stuck or hit the performance when retrieving data specific the user's friends in future.
Consider If I want to get all the activities from collection Activities done by my friends.
I think you could use advantage of noSql structure and save/serve some more info about friend
{
_id: ObjectID(abc),
name: "abc",
contacts: [{id:"def" name:"John"}, {id:"ghi", name:"Sari"} ]
}
To display basic list you will need just one get query, and then having name (or other important related details) - check for activities.
The extra overhead with this structure is a need to update name (and other details) every time when user updates it's name - but this is not a hammer - who changes its name frequently?

MeteorJS + MongoDB: How should I set up my collections when users can have the same document?

I wasn't quite sure how to word my question in one line, but here's a more in depth description.
I'm building a Meteor app where users can "own" the same document. For example, a user has a list of movies they own, which of course multiple people can own the same movie. There are several ways I've thought of structuring my database/collections for this, but I'm not sure which would be best.
I should also note that the movie info comes from an external API, that I'm currently storing into my own database as people find them in my app to speed up the next lookup.
Option 1 (My current config):
One collection (Movies) that stores all the movies and their info. Another collection that basically stores a list of movie ids in each document based on userId. On startup, I get the list of ids, find the movies in my database, and store them in local collections (there are 3 of them). The benefit that I see from this is I only have to store the movie once. The downside that I've ran into so far is difficulty in keeping things in sync and properly loading on startup (waiting on the local collections to populate).
Option 2 :
A Movies collection that stores a list of movie objects for each user. This makes the initial lookup and updating very simple, but it means I'll be storing the same fairly large documents multiple times.
Option 3:
A Movies collection with an array of userids on each movie that own that movie. This sounds pretty good too, but when I update the movie with new info, will an upsert work and keep the userids safe?
Option 3 seems sensible. Some of the choice may depend on the scale of each collection or the amount of links (will many users own the same movie, will users own many movies).
Some helpful code snippits for using option 3:
Upsert a movie detail (does not affect any other fields on the document if it already exists):
Movies.upsert({name: "Jaws"}, {$set: {year: 1975}});
Set that a user owns a movie (also does not affect any other document fields. $addToSet will not add the value twice if it is already in the array while using $push instead would create duplicates):
Movies.update({_id: ~~some movie id~~}, {$addToSet: {userIds: ~~some user id~~}});
Set that a user no longer owns a movie:
Movies.update({_id: ~~some movie id~~}, {$pull: {userIds: ~~some user id~~}});
Find all movies that a user owns (mongo automatically searches the field's array value):
Movies.find({userIds: ~~some user id~~});
Find all movies that a user owns, but exclude the users field from the result (keep the document small in the case that movie.userIds is a large array or protect the privacy of other user-movie ownership):
Movies.find({userIds: ~~some user id~~}, {userIds: 0});

Many to many relationship on Mongodb based e-learning webapp?

I am relatively new to No-SQL databases. I am designing a data structure for an e-learning web app. There would be X quantity of courses and Y quantity of users.
Every user will be able to take any number of courses.
Every course will be compound of many sections (each section may be a video or a quiz).
I will need to keep track of every section a user takes, so I think the whole course should be part of the user set (for each user), like so:
{
_id: "ed",
name: "Eduardo Ibarra",
courses: [
{
name: "Node JS",
progress: "100%",
section: [
{name: "Introdiction", passed:"100%", field3:"x", field4:""},
{name: "Quiz 1", passed:"75%", questions:[...], field3:"x", field4:""},
]
},
{
name: "MongoDB",
progress: "65%",
...
}
]
}
Is this the best way to do it?
I would say that design your database depending upon your queries. One thing is for sure.. You will have to do some embedding.
If you are going to perform more queries on what a user is doing, then make user as the primary entity and embed the courses within it. You don't need to embed the entire course info. The info about a course is static. For ex: the data about Node JS course - i.e. the content, author of the course, exercise files etc - will not change. So you can keep the courses' info separately in another collection. But how much of the course a user has completed is dependent on the individual user. So you should only keep the id of the course (which is stored in the separate 'course' collection) and for each user you can store the information that is related to that (User, Course) pair embedded in the user collection itself.
Now the most important question - what to do if you have to perform queries which require 'join' of user and course collections? For this you can use javascript to first get the courses (and maybe store them in an array or list etc) and then fetch the user for each of those courses from the courses collection or vice-versa. There are a few drivers available online to help you accomplish this. One is UnityJDBC which is available here.
From my experience, I understand that knowing what you are going to query from MongoDB is very helpful in designing your database because the NoSQL nature of MongoDB implies that you have no correct way for designing. Every way is incorrect if it does not allow you in accomplishing your task. So clearly, knowing beforehand what you will do (i.e. what you will query) with the database is the only guide.

Does MongoDB fit here? Modelling event registration with arbitrary extra data

I'm writing a basic event registration web application and I'm wondering whether MongoDB would be a good choice for the datastore and if so, how to model my domain. The app will be very small, so performance and scalability is not a concern, however when I started to think out the model in RDBMS third-normal terms it sounded quite complicated for what it is and from the bits and pieces I'm picking up about Mongo, sounded like a typical use-case. Is it?
The Application
The app allows creation of events, and for attendees to sign up to those events, giving their name, date of birth, etc. Easy, two tables with n:n join. The tricky part is that the organisers wish to be able to ask attendees of certain events for information particular to that event, for example on one event there might be a question about their accomodation preference. I narrowed it down to two types of question: those that require to select from certain options (will be an HTML select list) and questions which allow free-text answers. By the way it's a Rails app in case that matters.
Traditional RDBMS
In an RDBMS I would need perhaps a table for Constrained Question (where answers are from a list), a table for Answer Options, a table for Free Text Question and Free Text Answers; and to appropriately link this all up to the event and the atendee via a Signup. If you think about it the links between the tables are rather complicated!
Mongo
Would this be simpler to model in Mongo? I thought that perhaps besides the Attendee and Event collections, there could be a Question collection which has its allowed answers embedded, if there are no answers then it's free text. A Signup collection that relates an Attendee to an Event and references the id of the relevant Question, and embeds the text of the answer? If the text of an answer option ever changes it might get complicated... but I guess that's the tradeoff of Mongo.
Is this a good use case for Mongo on should I stick with Postgres? Can you suggest a (or improve my) schema?
Mongodb is a awesome tool for this job. You can pretty much utilize the embedded collection here to maximize the performance.
Your current schema is perfectly fine. By tweaking this a little bit with embedded collections , it will be a blast.
For instance, instead of keeping the Question collection seperately, you can have this inside Attendee. This will let you store all relevant info about the attendee in single place.
- Attendee
- Info
- Event_id
- Questions {
-Question id
- Answers [ {
- answer id 1
- or answer text
},{
- answer id 2
- or answer text
}],
}
Also you can cache the frequently used data about the attendees inside the Event collection.
This will be immensely useful for quickly displaying home page data.
For example, you may need to display the users who are attending the event and their count in the event home page. To do that you need to first query the event and query the Attendees.
But i suggest you to do store the attendee_id/name inside the Event as an array, which looks
Event :
- Info
- attendees {
attendee_id : 'xx'
name : 'Fletch'
}
So you can populate the event home page with a single db call to Event collection. Because you can get a minimum info to be displayed about the user and total user count for an event will be retrieved here itself. You can query the attendee when you need to display more info about the user like his question/answers.
Hope this helps