related tables in mongodb - node.js

I have two related tables in mongodb.
such as users and students.
Since each student is also a user, I store the userid as a userid in the students table. Should I do this? What is the best practice in this regard?
I'm a little confused as I'm coming from a relational database.
enter image description here
enter image description here

If you will follow that pattern, will be better if you save the userId in the students collection (not a table) as ObjectId instead of string, because that will allow you to do lookups easily.
Another idea can be save the type attribute in users collection to specify what kind of user a user is. Because as I see your are using exactly the same information in both collections, the only thing that will be different is the context.

Related

Mongodb and node js transaction alternative and relations

I am trying to implement relations on collections. My requirement is
Post request 1, json body:
{
"username":"aaa",
"password":"bbb",
"role":"owner",
"company":"SAS"
}
Post request 2, creating from first document so I got company name from previous json body:
{
"username":"eee",
"password":"fff",
"role":"engineer",
"company":"SAS"
}
Post request 3, creating from first document so I got company name from previous json body:
{
"username":"uuu",
"password":"kkk",
"role":"engineer",
"company":"SAS"
}
Post request 4, next company json body:
{
"username":"hhh",
"password":"ggg",
"role":"owner",
"company":"GVG"
}
Here company is foreign key field. How can I achieve company with id field without failing one another like transactions.
In mysql I will create two tables company, user and using transactions i will insert in both tables in single post using id's if any update in company name id will remain same for owner and engineer.
How can I achieve these in mongodb, with node.js?
In online searches I have found most suggest avoid transactions and using mongodb functionalities like mongodb embedded.
I would suggest you to start with making schemas for user and company using mongoose. Its an ODM(object document mapper) which is almost always used with node.js and mongodb
Now this is one to many relations. In relational databases as you have mentioned, you would make a company table and a user table.
In mongodb it "depends". If its one to "few" relationship you would just nest the users array into company's collection. Then since you are only updating a single document(pushing user to users array in company's document), you wont be needing any transactions. Single document update is always atomic(no matter how many fields you update on the same document).
But if each company can have large number of users(ever growing nested array is not good, as it can cause data fragmentation and bad performance), then its better to store the company's id in user's document. And even in this case you would not need transaction, since you are not updating the company's document.
Another reason for storing user as separate collection, is query issues. If you just want to query users its difficult if they are nested in companies. So basically you need to consider how you will query and figure out the number of relations then decide to nest of store is separate collections.
First of all, you should notice that Mongo is document-oriented DB, not a relation one. So if you need transactions and relation model, probably you should try to use any SQL relative database? Especially if you are more familiar with them?
About relation and data modeling: you should this article (or even entire part) at official Mongo docs, Data Modelling.
TL:DR, you could create two separate collections (the same as tables in SQL) like employees, and companies (by default, collection's name will be in plural forms). And store data separately.
So you employees will be stored like you mention above, but companies will be like:
{
_id: ObjectID("35473645632")
name: "SAS"
}, ...
and as for your employees collection, you should store not like, "company":"SAS", but, "company":"ObjectID("35473645632"), or even as array if you want it too. But don't forgot to edit you schema than.
You could use not just MongoDB's default _id but your own one, it could be any unique number/string combination
So, if your company will be renamed, your connection with other documents (employees) still will be there.
To request all/any of your employees with company name's you should use .aggregation framework with $lookup, instead of .find.

MongoDB - When to add SubDocuments and when to Ref

Im using MongoDB for storing information for a nodeJS application and a doubt came to my mind, after finding that it is possible to use ObjectID to ref another document. As it is known, MongoDB is a no-SQL db, so there is no need for consistency whatsoever and information can be repeated.
So, lets say, I have a collection for users and one of their field values is 'friends', which is an array of this user friends (another users). What is the best practice, saving all the user info there (thus repeating the same thing over and over again throughout the DB) or saving only the ObjectID of the friendUser (makes way more sense to me, but it sounds kinda SQL mindset). I'm not really getting when should I use each of the options, so a professional opinion would be very appreciated.
To model relationships between connected data, you can reference a document or embed it in another document as a subdocument.
Referencing a document does not create a “real” relationship between these two documents as does with a relational database.
Referencing documents is also known as normalization. It is good for data consistency but creates more queries in your system.
Embedding documents is also known as denormalization.
The benefit of Embedding approach is getting all the data you need about a document and it’s sub-document(s) with a single query. Therefore, this approach is very fast. The drawback is that data may not stay as consistent in the database.
Important
If one document is to be used by many documents then better create a referenced doc.
i. Will Save Space.
ii. if any change required, we will have to update only the referenced doc
instead of updating many docs.
Create sub doc(embedded)
i. If another document is not dependent on the subdocument.
Source: https://vegibit.com/mongoose-relationships-tutorial/
Recommended reading:
MongoDB Applied Design Patterns by Rick Copeland
To Embed or Reference

MongoDB, how to manage user related records

I'm currently trying to learn Node.js and Mongoodb by building the server side of a web application which should manage insurance documents for the insurance agent.
So let's say i'm the user, I sign in, then I start to add my customers and their insurances.
So I have 2 collection related, Customers and Insurances.
I have one more collection to store the users login data, let's call it Users.
I don't want the new users to see and modify the customers and the insurances of other users.
How can I "divide" every user related record, so that each user can work only with his data?
I figured out I can actually add to every record, the _id of the one user who created the record.
For example I login as myself, I got my Id "001", I could add one field with this value in every customer and insurance.
In that way I could filter every query with this code.
Would it be a good idea? In my opinion this filtering is a waste of processing power for mongoDB.
If someone has any idea of a solution, or even a link to an article about it, it would be helpful.
Thank you.
This is more a general permissions problem than just a MongoDB question. Also, without knowing more about your schemas it's hard to give specific advice.
However, here are some approaches:
1) Embed sub-documents
Since MongoDB is a document store allowing you to store arbitrary JSON-like objects, you could simply store the customers and licenses wholly inside each user object. That way querying for a user would return their customers and licenses as well.
2) Denormalise
Common practice for NoSQL databases is to denormalise related data (ie. duplicate the data). This might include embedding a sub-document that is a partial representation of your customers/licenses/whatever inside your user document. This has the similar benefit to the above solution in that it eliminates additional queries for sub-documents. It also has the same drawbacks of requiring more care to be taken for preserving data integrity.
3) Reference with foreign key
This is a more traditionally relational approach, and is basically what you're suggesting in your question. Depending on whether you want the reference to be bi-directional (both documents reference each other) or uni-directional (one document references the other) you can either store the user's ID as a foreign user_id field, or store an array of customer_ids and insurance_ids in the user document. In relational parlance this is sometimes described to as "has many" or "belongs to" (the user has many customers, the customer belongs to a user).

MongoDB standards for User/Room relations

So I have this MEAN-project I hobby on in my spare time.
Right now I'm setting up users and rooms, and am a bit hesitant about progressing further, as I am unsure about the proper protocol of db's in general.
As I recall, you're not supposed to have a Many-To-Many relationship; rather, you're supposed to have a relation table.
Right now, my User schema has an array of rooms he is in, and my Room schema has an array of users tied to it (the third and last schema being Message).
Is it better to have a userroomrelation doc that holds a PK, an id of one room, and then a list of all users in this room?
Thanks,
Rasmus
MongoDB isn't a relational database like *SQL databases (hence why MongoDB is called NoSQL), so using a relation table is fairly inefficient in Mongo. Holding an array of user _id's in the room collection is about as ideal as you could get, if you don't want repeat data.
Here are some more indepth answers on many-to-many in MongoDB.
How can a User be in more than one room? Isn't that just a property on the User? And if you index that why would you also need to store it on the Room?
There is no one right way, it really depends on how many of each object you have and if it's a small number (as rooms and users implies) you may be better with a simpler and more robust (cannot store impossible values) approach like having a single property on a user RoomId. That's never going to be inconsistent and if you need to find the set of users in a given room it's a cheap query.
In MongoDB you CAN denormalize the data and store an array on each object containing part or all of the other object, but you can also create an effective join collection if you want to.
For example you could have a collection {UserId, RoomId, DateTimeEntered, DateTimeLeft} with appropriate indexes which allows you to quickly find all the users in a given room at a given time. Once you have the set of Ids you could go load them if you need them for display OR you could add the fields you need for display to this table {UserId, UserName, ...} BUT then you have the problem of maintaining that data if it ever changes OR keeping it intact if you need to know that when they entered the room that's what it was called.
There are also a TON of other questions on StackOverflow relating to how you should store related data, I suggest you go read those also.

Which mongoose model would be more efficient?

I am new to no-sql. I am trying to build a simple e-commerce app in nodejs. Now for the product i need to build CRUD operations so that only owner can edit them, rest have READ-ONLY access. The main question is which would be a better implementation ?
The current code that i have is like
var mongoose = require('mongoose');
module.exports = mongoose.model('product',new mongoose.Schema({
owner : {type: String},
title : {type: String},
...
}));
The owner is actually the _id from my user model. Basically this is something like a foreign key. Is this the valid method to go around or should i add an array inside the user model to store the list of objects that he owns ?
Also i would like to have validation if what i just did for owner, storing UID in String is best practice or should i do something else to reference the user model.
Thanks in advance for helping me out.
The whole point of document databases is you shouldn't have foreign relationships; All the data your document needs should be denormalized in the document.
So inside your product document, you should be duplicating all the owner details you need. You can store their _id as well for lookup, but don't use a string for this, use an actual ObjectId().
For more about denormalization see The Little MongoDB Book
Yet another alternative to using joins is to denormalize your data. Historically, denormalization was reserved for performance-sensitive code, or when data should be snapshotted (like in an audit log). However, with the ever- growing popularity of NoSQL, many of which don’t have joins, denormalization as part of normal modeling is becoming increasingly common. This doesn’t mean you should duplicate every piece of information in every document. However, rather than letting fear of duplicate data drive your design decisions, consider modeling your data based on what information belongs to what document.

Resources