Database Management - Should I use multiple databases? - mysql

I have an issue with the planning of my program. I am not sure what I should do.
Here my idea:
The program has users, the users can create persons, those persons have many attributes and every user can create multiple persons. Also there's a table 'todo' that is made to assign tasks to persons.
(-> = attributes, --> connected tables)
Users -> username, password, email, usertype, id
Person -> id, src, firstname, middlename(s), lastname, birthdate, description, height, favourites, dislikes, hates, boundaries, disorders, fronting
--> personType, pronouns, source, fav Colors, fav Foods, kids (connection to "Person"), relationships (connection to "Person")
Todo -> id, due, title, description
--> assignedTo (connection to "Person")
My issue:
As you can see a person has multiple attributes and a user can create multiple persons with todos. And I am not sure how practical this is to handle, if the privacy is reassured and what the most efficient option is.
My Question:
Should I use a system where every user gets its own database with his persons and todos and stuff?
or
Should I use 1 Database for everything?
or
is there even a better solution?

I would only consider the 'multiple databases' solution if it was an answer a technical problem that you have (legacy datasources that you don't want to merge for instance).
The security concerns that you have regarding people accessing data that they shouldn't have is important, but the solution is a solid security model, and not necessarily segregating the data in multiple databases
Since you are starting your program and can choose your option in a more functional / data model driven approach, and as such the single database option is way more friendly.
You will be able to properly model and enforce the relationships between your objects, and define a solid model.

Related

Database design: User Types: Many fields in users table or separate tables?

I'm developing an Uber like app using Laravel, as you may know it has different user types, there can be drivers and regular users. i'm not sure how to structure the database since drivers can have other fields and relations that regular users do not but i need both types to be able to login. Also users can take a drive and rate the driver and only drivers can have their bio, license number, years driving, rating and just them can have relations like to the car the are driving and so on...
I want to know your thoughts about what is the best approach to handle this type of situation?
Keep drivers and users in the same users table with the drivers fields nullable and a type field to know if it is a driver or a regular user?
Q: If I go with this option how can I guarantee the driver of a ride is effectively a driver and not a simple user?
users
id
name
password
type
driver_license_number
driver_years_driving
driver_rating
Keep credentials of both drivers and regular users in the users table and store drivers specific info in another?
Q: If I go with this option should drivers have their own primary key or use the user's primary key? which table should keep the 1:1 relationship? the users table? the drivers table?
users
id
name
password
drivers
id
user_id
license_number
years_driving
rating
You are tying two different things together under the term user: user as in “someone who registered in my application” and user as in “someone who’s using my application to get rides”. Both drivers and non-drivers are users in the first definition, but not in the second.
What's confusing is that the Driver entity is just a User entity with more fields, so it's possible to not represent the entity at all, just add more columns to the User entity, and, responding to your first question, add a is_driver column to tell which entity is which.
By doing this, you are crippling your database capabilities to guarantee your data is valid. You now can have a Driver row without a driver_license_number, because your database doesn't know what a Driver is, oops.
There's a lot of benefits by being explicit in your database schema. Part of the database work is to guarantee data consistency, help your database help you.
My suggestion is to go a step further. Credentials are one thing, they get their table. Users are another, they get their table (in your example, users seems to have no data at all, but they will probably have more things than just their name). Drivers are yet another, they get their table too.
credentials
id
username
password_hash (you are hashing your passwords, right?)
users
cred_id
... other user related info
driver
cred_id (you can get with user_id, but it's an unnecessary join)
user_id
... driver related info
I believe you should use two separate tables. This would avoid having lots of nullable fields that are not shared between riders and drivers. Furthermore, if these entities are frequently changing, ALTER TABLE will be a bit of a pain at scale.
Joins of course are a little bit more expensive across the two tables, but the query is more natural to write because of our normalization choice.
As a side note, this application will eventually have trouble scaling no matter which way you choose to write the tables, because MySQL cannot easily be horizontally scaled.
But, if you want easy querying and avoidance of nullable fields, two separate tables sounds like the right choice to me.
Consider 3 tables (plus, perhaps, some others):
Persons -- this contains the stuff that is common to both Drivers and Riders, such as login.
Riders -- bio, etc
Drivers
If it would make things handier for you, build two views:
Rider_all -- JOIN between Persons and Riders
Driver_all -- JOIN between Persons and Drivers

Advanced targeting like Facebook Sharings (Flexible ACL) DB Design

I've been trying to develop an internal staff portal for our company. There are departments, job grades, working areas, roles (user, editor, admin, super admin, etc...) and special groups (executives, etc) for user grouping.
User must have one (only one) department.
User must have one (only one) job grades.
User must work in minimum one area.
User must have one (only one) roles.
User may have one or more special groups.
Job grades and roles are hierarchical (an grade or role may be inherited of another one) but other ones not.
Users will see only allowed menus and access permitted routes.
User will also select which users can view it when posting a new content.
e.g:
Combination 1: (IT or Finance department) and (Job Grade is one of 9,10,11) and (Area is one of 1,5,8) and (Exclusive special group is one of 1,5,8) except user id=1
Combination 2: (HR department) and (Job Grade is 11) and user_id=3,4,5
Combinations can be related as AND/OR among themselves like Combination 1 AND combination 2
So, there will be lots of contents and every content will have different group permissions. I try to create a DB schema but it's very hard to get all contents that is visible to logged in user. Serialized data would be good for saving combination sets in db but it looks like impossible with serialized data. Is there an advantage to using MongoDB for this issue? How can i save combinations of group/user permissions in tables also?
I researched lots of ACL and RBAC examples but can't find the optimal solution. Please help.
Btw, i use Laravel Framework.
Thanks.
You need to look into attribute-based access control (ABAC - Wikipedia) and the eXtensible Access Control Markup Language (XACML). NIST, the National Institute of Science & Technology gives a great intro to ABAC here.
XACML will give you the ability to express fine-grained access control policies that use you attributes. In your question you have:
user attributes
department
job grade
working area
role
group
object (resource) attributes
content type
content location
content classification
With XACML you can write rules such as:
A user with grade==1 can do the action==edit on content of type==post
if content.department==user.department.
You can have as many rules as you like including conflicting rules or environment rules (deny access before 9am).
Have a look at the ALFA plugin for Eclipse to write your own policies (Wikipedia | Download).
HTH,
David

What is a better data model to use to store user profiles?

I am working on the data model for a relational database where I have to store User Information as well as User's profile such as Education Level, personal interests, hobbies, and etc. Similar to what most of the social networking sites have or any other systems that allow you to build a profile.
I cannot decide if it would be better to store all this information in one Users table, or break it into 2 tables.
If I would break it into two tables I would have Users table that would just store UserID, Name, e-mail, DOB, gender.
UserProfiles would store the rest of the stuff pertaining to a profile, sharing the same UserID with Users table
If there are multiple profiles of a single user means one to many relation then i would recommend you to create 2 tables one is user and other is user-profile.
If one user have only one profile then your should create only one table with both attributes on User as well as profile.
Go for the more modular design, this will allow for more flexibility and control. The only time I would recommend keeping the data in a single table is if you plan to query the same data frequently.
There is a great article here which goes into depth as to why joins are expensive. You should ultimately base your decision off the information provided in the link, however as I mentioned before if you plan to query the two tables together frequently then keep the data in a single table.
I think,in order to decide which data model to chose, just look at some of the similar requirement Datamodels, which are presented in this Datamodel Library.
Specific to your User-profiles Datamodel Requirement, this link may be useful.
Hope those links will be useful. OR I got this Data model image depicting facebook type data model:

MySQL database model for signups with and without addresses

I've been thinking about this all evening (GMT) but I can't seem to figure out a good solution for this one. Here's the case...
I have to create a signup system which distinguishes 4 kinds of "users":
Individual sign ups (require address info)
Group sign ups (don't require address info)
Group contact (require address info)
Application users (don't require address info)
I really cannot come up with a decent way of modeling this into something that makes sense. I'd greatly appreciate it if you could share your ideas.
Thanks in advance!
Sounds like good case for single table inheritance
Requiring certain data is more a function of your application logic than your database. You can definitely define database columns that don't allow NULL values, but they can be set to "" (empty string) without any errors.
As far as how to structure your database, have two separate tables:
User
UserAddress
When you have a new signup that requires contact info, your application will create records in both tables. When a new signup doesn't require address info, your application will only create a record in the User table.
There are a couple considerations here: first, I like to look at User/Group as a case of a Composite pattern. It clearly meets the requirement: you often have to treat the aggregate and individual versions of the entity interchangeably (as you note). Implementing a composite in a database is not that hard. If you are using an ORM, it is pretty simple (inheritance).
On the other part of the question, you always have the ability to create data structures that are mostly empty. Generally, that's a bad idea. So you can say 'well, in the beginning, we don't have any information about the User so we will just leave all the other fields blank.' A better approach is to try and model the phases as if they were part of an FSM. One of the clearest ways to do this in this particular case is to distinguish between Users, Accounts and some other more domain-specific entity, e.g. Subscriber or Customer. Then, I can come and browse using User, sign up and make an Account, then later when you want address and other personal information, become a subscriber. This would also imply inheritance, and you have the added benefit of being able to have a true representation of the population at any time that doesn't require stupid shenanigans like 'SELECT COUNT(*) WHERE _ not null,' etc.
Here's a suggestion from my end after weighing pro's and con's on this model. As I think the ideal setup is to have all users be a user entity that belong to a group without differentiating groups from individuals (except of course flag a group contact person and creating a link with a groups table) we came up with the alternative to copy the group contact user details to the group members when they group is created.
This way all entities that actually are a person will get their own table.
Could this be a good idea? Awaiting your comments :)
I've decided to go with a construction where group members are separated from the user pool anyway. The group members eventually have no relation with a user since they don't require access to mutating their personal data, that's what a group contact person is for. Eventually I could add a possibility for groups to have multiple contact persons, even distinguishing persons that are or are not allowed to edit any member data.
That's my answer on this one.

Permissions for web site users

I'm working on a web site where each user can have multiple roles/permissions such as basic logging in, ordering products, administrating other users, and so on. On top of this, there are stores, and each store can have multiple users administrating it. Each store also has it's own set of permissions.
I've confused myself and am not sure how best to represent this in a db. Right now I'm thinking:
users
roles
users_roles
stores
stores_users
But, should I also have stores_roles and stores_users_roles tables to keep track of separate permissions for the stores or should I keep the roles limited to a single 'roles' table?
I originally thought of having only a single roles table, but then what about users who have roles in multiple stores? I.e., if a user is given a role of let's say 'store product updating' there would need to be some method of determining which store this is referring to. A stores_users_roles table could fix this by having a store_id field, thus a user could have 'store product updating' and 'store product deletion' for store #42 and only 'store product updating' for store #84.
I hope I'm making sense here.
Edit
Thanks for the info everyone. Apparently I have some thinking to do. This is simply a fun project I'm working on, but RBAC has always been something that I wanted to understand better.
This is probably obvious to you by now, but role based access control is hard. My suggestion is, don't try to write your own unless you want that one part to take up all the time you were hoping to spend on the 'cool stuff'.
There are plenty of flexible, thoroughly-tested authorization libraries out there implementing RBAC (sometimes mislabeled as ACL), and my suggestion would be to find one that suits your needs and use it. Don't reinvent the wheel unless you are a wheel geek.
It seems likely to me that if I have permission to do certain roles in a set of stores, then I would probably have the same permissions in each store. So having a single roles table would probably be sufficient. So "joe" can do "store product updating" and "store product deletion", then have a user_stores table to list which stores he has access to. The assumption is for that entire list, he would have the same permissions in all stores.
If the business rules are such that he could update and delete in one store, but only update, no delete, in another store, well then you'll have to get more complex.
In my experience you'll usually be told that you need a lot of flexibility, then once implemented, no one uses it. And the GUI gets very complex and makes it hard to administer.
If the GUI does get complex, I suggest you look at it from the point of view of the store as well as the point of view of the user. In other words, instead of selecting a user, then selecting what permissions they have, and what stores they can access, it may be simpler to first select a store, then select which users have access to which roles in that store. Depends I guess on how many users and how many stores. In a past project I found it far easier to do it one way than the other.
Your model looks ok to me. The only modification I think you need is as to the granularity of the Role. Right now, your role is just an operation.
But first, you need a store_role table, a joint table resolving the Many-to-many relationship b/w a role and a store. ie, one store can have many roles and one role can be done in many stores.
Eg: StoreA can CREATE, UPDATE, DELETE customer. and DELETE customer can be done in StoreA, StoreB and StoreC.
Next, you can freely associate users to store_role_id in the user_store_roles table.
Now, a user_store_role record will have a user_id and a store_role_id:
A collection of
SELECT * FROM USER_STORE_ROLE WHERE user_id = #userID
returns all permitted operations of the user in all the stores.
For a collection of users's roles in a particular store, do an inner join of the above to user_store table adding a WHERE part of like
where STORE_ROLE.store_id = #storeID
Put a store_id in the user_roles table.
If this is Rails, the user model would have_many :stores, :through => :roles