How should I handle two different types of users in database? - postgresql

I am building a ecommerce application with two different types of users, users who shop and vendors/brands.
Should I make two tables for each user like?
User| id, email, password, username, address, stripeCustomerId
Brands| id, email, password, username/brandName, shippingRate, address, stripeAccessToken etc.
Or should I make it like so:
Users| id, email, password, username, address, stripeCustomerId
Brands| userid, etc...

This is an example of trying to model the object-oriented notion of inheritance in a relational database. If you search for that term, you'll find several answers on Stack Overflow.
In your case, I think you have 3 logical entities:
User: email, password, username, address...
Customer (is a type of user): StripeID
Vendor (is a type of user): shipping rate, stripe token
How you model those logical entities to physical objects in your database is mostly a question of trade-offs - the other answers explain those.
I assume there will be significant differences in both the behaviour and attributes between "customer" and "vendor".
I also assume your data model will evolve over time - for instance, you probably need to store more than one address for each user (shipping, billing), you probably have different lifecycles for "customers" (new, registered, registration confirmed, payment confirmed) and "vendors" (new, approved, rejected).
If those things are true, I'd just bite the bullet and have 2 tables, customer and vendor. This means you can evolve their behaviour more easily - you don't have to worry about needing a slightly different address logic between two "customer" and "vendor", you just build what you need. Your schema is a little more self-explanatory - your foreign keys go to tables that say what they do (products -> vendors, not products -> users).

It shouldn't be two tables, but three :D
1. users (id, name, password, )
2. customers (user_id, customer_specific_fields)
3. vendors (user_id, vendor_specific_fields)

Related

ScyllaDB mutual friend relation data modeling

I'm working on a mobile App with social features, I'm currently trying on implement mutual friend relations with Scylla. I have chosen Scylla because the Friend Service will be a key feature with high TPS since a lot of other services need access to a users friends and friend relations are generally a good fit for NoSQL.
Mutual friend relation means, if user_1 accepts the friend request of another user_2, user_2 should have user_1 as friend, but user_1 should also automatically be friends with user_2.
My goal is to design a Schema that allows all my access patterns with minimal response time, so optimally one request for every access pattern. Less data duplication would be nice but not mandatory.
Access Patterns:
Get Friends of a user by the user's id
Get Incoming Friend Requests by user id
Get Relation between two users by specifying both user id's
The query should allow us to conclude if the two users are friends, if one requested the other to be friends or if they are not friends.
Data Manipulation
Create Friend Request
Decline Friend Request
Accept Friend Request
This should result in a mutual friend relation between the requester and requested.
Remove Friend Relation
This should remove the friend relation for both users.
My Current Design
Here I will explain my current Schema and which access patterns it allows me to do and what could be improved.
This is my Schema, no data duplication just one table with the Primary Key user_id, accepted, friend_id
CREATE TABLE IF NOT EXISTS friend_relations (
user_id text,
friend_id text,
accepted boolean,
requested_at timestamp,
accepted_at timestamp,
PRIMARY KEY (user_id, accepted, friend_id)
);
GetFriends
SELECT * FROM friend_relations WHERE user_id=? AND accepted=true;
GetIncomingFriendRequests
When a Friend Request is inserted the receiver is the user_id so it is only possible to get Incoming Friend Request but not outgoing.
SELECT * FROM friend_relations WHERE user_id=? AND accepted=false;
GetFriendRelation
This is my current Pain Point. It would be easy to know if user_1 is
friends with user_2 since their would be a record for both of them
saying the other user is their friend (because of mutual friend
relation). But when I want to know if one user requested the other, I
would need to do a query like below:
SELECT * FROM friend_relations WHERE user_id IN (user_1,user_2) AND accepted=false AND friend_id IN (user_1,user_2)
This way I would know if either user_1 requested user_2 or the
other way.
I combined both queries into:
SELECT * FROM friend_relations WHERE user_id IN (user_1,user_2) AND accepted IN (true, false) AND friend_id IN (user_1,user_2).
The many IN relations give some headaches since I'm not sure if this could cause unpredictable performance when one id is in a completely different partition on a different Node.
Data Manipulation
Create Friend Request
INSERT INTO friend_relations (user_id, friend_id, accepted, requested_at) VALUES (requested_user, requester, false, now).
Here I'm switching the requester to the friend_id and the person who get's requested (requested_user) is the user_id. That way we can find all friend requests to a user which is more important than finding the friend requests sent by a user.
Decline Friend Request
DELETE FROM friend_relations WHERE user_id=? AND accepted=false AND friend_id=?;
This is simple since the person who wants to decline is the user_id and the friend_id is the person who requested.
Accept Friend Request
This is more complicated since I need to batch three cql statements.
Delete the friend request where the accepting user is the
user_id, accepted=false and the friend_id is the requester. I
can't update the relation since accepting is part of the primary
key.
Insert mutual friend relation by inserting two friend relations
with accepted=true and switching the user_id and friend_id for
one of the inserts, as this way the other user will be found by
GetFriends method for both users.
Remove Friend Relation
DELETE FROM friend_relations WHERE user_id IN (user_1,user_2) AND accepted=true AND friend_id IN (user_1,user_2);.
Relatively easy, just delete relation for both sides of users.
These are all my thoughts that went into designing my current Schema but I'm still not completly convinced by it, since a very important access pattern GetRelation uses so many IN relations and accepting a Friend Request is quite complicated. But I also find it hard to imagine a better Schema which could include Materialized Views, perhaps to separate the friend requests from the friend relations, because then the GetRelation method would need to query the other table if one doesn't return a record (Two network requests).

updating and modeling nosql record

So in a traditional database I might have 2 tables like users, company
id
username
companyid
email
1
j23
1
something#gmail.com
2
fj222
1
james#aol.com
id
ownerid
company_name
1
1
A Really boring company
This is to say that user 1 and 2 are apart of company 1 (a really boring company) and user 1 is the owner of this company.
I could easily issue an update statement in MySQL or Postgresql to update the company name.
But how could I model the same data from a NoSQL perspective, in something like Dynamodb or Mongodb?
Would each user record (document in NoSQL) contain the same company table data (id, ownerid (or is owner true/false, and company name)? I'm unclear how to update the record for all users containing this data then if the company name needed to be updated.
In case you want to save the company object as JSON in each field (for performance reasons), indeed, you have to update a lot of rows.
But best way to achieve this is to have a similar structure as you have above, in MySQL. NoSql schema depends a lot on the queries you will be making.
For example, the schema above is great for:
Find a particular user by username, along with his company name. First you need to query User by username (you can add an index), get the companyId and do another query on Company to fetch the name.
Let's assume company name changes often
In this case company name update is easy. To execute the read query, you need 2 queries to get your result (but they should execute fast)
Embedded company JSON would work better for:
Find all users from a specific city and show their company name
Let's assume company name changes very rarely
In this case, we can't use the "relational" approach, because we will do 1 query to fetch Users by city and then another query for all users found to fetch the company name
Using embedded approach, we need only 1 query
To update a company name, a full (expensive) scan is needed, but should be ok if done rarely
What if company name changes ofter and I want to get users by city?
This becomes tricky, NoSQL is not a replacement for SQL, it has it's shortcomings. Solution may be a platform dependent feature (from mongo, dynamodb, firestore etc.), an additional layer above (elasticSearch) or no solution at all (consider not using key-value NoSQL)
Depends on the programming language used to handle NoSQL objects/documents you have variety of ORM libraries to model your schema. Eg. for MongoDB plus JS/Typescript I recommend Mongoose and its subdocuments. Here is more about it:
https://mongoosejs.com/docs/subdocs.html

Firestore One-to-Many Relationship Query

I need help, how to make one-to-many queries, for example:
I have 2 collections: customers, orders
customers{
customerId,
fullName,
company,
email,
}
orders{
orderId,
customerId,
createdAt,
}
I want to list all orders in a table with some customers data (customer full name, compa
Congratulations, you are alone in the dark Firestore Forest. Bring back all you have learned of DBMS at the college days and get you hands dirty.
Alternative 1:
First you need to filter the customers that satisfies your criteria. Then, load ALL your orders and filter mannually. I'm not kidding, saddly. The same applies if you need to order orders by customer name, for example. I'll be very happy to see someone downvote this for being wrong.
Reference: https://firebase.google.com/docs/firestore/query-data/queries
Alternative 2:
Stop using Firestore. I think you already done that.

What's the relationship between res.partner and res.user?

I am new to odoo v8 and i am not able to understand the relationship between res_partner and res_users tables and also with hr_employee table are they all related?
The relationship between res.partner and res.user is that res.user inherits from res.partner using an inheritance type called "Delegation Inheritance" (see documentation).
Because of "Delegation Inheritance" every res.user record has a mandatory internal connection to a corresponding res.partner record using a field partner_id. What is this connection all about is to directly use all the fields of res.partner to store data shared by res.user and res.partner (i.e. name, phone, etc... if for example you refer to phone property of a record of res.user you'll get the value stored in the corresponding res.partner record) so res.user has to define fewer number of fields on it's own, like password, login, etc..
Note also that because of this relation res.user can NOT exist in the system without corresponding res.partner, it's why every res.user has one, but nonetheless res.partner can exist without res.user.
hr.employee have m21 with res.users (user_id)
res.users have m21 with res.partner(partner_id)
Actually only res.users has a "real" relationship to res.partner, because with every user odoo will create a partner (per default no customer and no supplier). this partner will be used e.g. for emails and the followers system in odoo.
But you can have partners without users, too. That will be a normal partner, for defining customers and suppliers.
And finally there is the employee. You can set a user on it. If i recall right, the user will be used for attendances and timesheets.

How to relate entities - users with multiple roles

I have 3 entities to represent Users, Roles and Conferences
So far I got this diagram:
So,
-A user can be associated with zero or more conferences.
-A conference may have one or more users.
and...
-The same user can have different roles depending on which conference he is.
but...
-How can I improve the diagram so i can see the different roles of a user in all the conferences he has attended?
[UPDATE]
From your description it sounds like users belong to roles, and then the combination of userRoles belongs to a conference. So, without the fancy diagram, your entities would be something like this...
Users
Id
Roles
Id
Conferences
Id
UserRoles
UserId
RoleId
ConferenceUserRoles
ConferenceId
UserId
RoleId
You may need to add a "UserRoleId" to UserRoles and use that in ConferenceUserRoles. I'm not exactly sure how EF will handle the three-way relation table.
Hope this helps!