How to add additional attribute to many-to-many relationship - mysql

I have a database that keeps tracks of my (registered) users. Every user can be (and is by default) part of a team. A team groups together multiple users.
Since users can be part of multiple teams, I would like for them to be able to toggle on and off certain teams. When turned off, the team's data won't be shown to that user in the frontend. When multiple organizations are toggled on, all the data is shown simultaneously.
So my question is: How should I go about this architecturally? Is there a "right" way of doing things? I am using Prisma with a Planetscale (MySQL) database, however I do appreciate any theoretical answers as well.
In Prisma, my (simplified) schema currently looks like this:
model User {
id String #id #default(cuid())
name String?
teams Team[]
}
model Organization {
id String #id #default(cuid())
name String
users User[]
}
Technically, I would think that I would simply like to mark a team as "active" or "inactive", but I'm not seeing how to do that exactly. Simply adding an active Boolean attribute to the team wouldn't work, since I won't be able to tell which user that applies to, correct?
The only way that I know that works is to have both an ActiveTeam reference as well as an InactiveTeam reference on my user table instead of having just a teams reference. This does seem unnecessarily complicated though and I'm hoping there is an easier way of doing it.

As #Barmar said, you can use a juntion table to accomplish this.
The schema will look somthing like this:
model User {
id String #id #default(cuid())
name String?
userTeams User_Team[]
}
model Team {
id String #id #default(cuid())
name String?
userTeams User_Team[]
}
model User_Team {
userId String
user User #relation(fields: [userId], references: [id])
teamId String
team Team #relation(fields: [teamId], references: [id])
isActive Boolean
##id([userId, teamId])
}
// Your other models ...

Related

Multiple Foreign Key from the same table

I have a Laravel application with a MySQL database that has 3 tables: Publication, Comment and User.
When I display a publication to user I call WS GET Publication By Id and WP GET Comment By Publication Id to display all comments related to that publication.
I want to know if there's a way to avoid Calling WP GET User By Comment Id for each Comment, because when I display a comment I also need to display some information for user who commented.
Can I add multiple user Foreign Keys in table Comment and use them?
Thanks in advance.
This is a very generic usecase. Can you see if this answers your question.
Publication model{
whatever fields you have,
//Comments --> One to many relation with Comment model
public function comments()
{
return $this->hasMany('App\Comment');
}
}
Comment Model{
whatever fields you have,
//User --> One to one relation with User model
public function user()
{
return $this->hasOne('App\User');
}
}
User Model{
fields...
}
In your controller, you can get the publications with comments and users by using with function.
$pub = Publication::first()->with('comments.user');
I hope this helps.

How would you model a collection of users and friends in Firebase?

I'm trying to create a database (json) with Firebase.
I searched the docs and the net but couldn't find a clear way to start.
I want to have a database of users.
each user (represented as UID) should have a nickname and a list of friends.
I tried making a .json file that looks like this:
{
users:{
}
}
and adding it to the Firebase console to get started but it wouldn't work.
How can I do it?
the database should look like this:
{
users:{
UID:{
nickname: hello
friends: UID2
}
UID2:{
nickname: world
friends: UID
}
}
I don't know if I got that right, so I would really appreciate any help you guys could give me at this subject.
Thanks in advance!
Seems like a good place to start. I would make two changes though.
keep the list is friends separate
keep the friends as a set, instead of a single value or array
keep the list is friends separate
A basic recommendation when using the Firebase Database is to keep your data structure shallow/flat. There are many reasons for this, and you have at least two.
With your current data structure, say that you want to show a list of user names. You can only get that list by listening to /users. And that means you don't just get the user name for each user, but also their list of friends. Chances that you're going to show all that data to the user are minimal, so that means that you've just wasted some of their bandwidth.
Say that you want to allow everyone to read the list of user names. But you only want each user to be able to read their own list of friends. Your current data structure makes that hard, since permission cascades and rules are not filters.
A better structure is to keep the list of user profiles (currently just their name) separate from the list of friends for each user.
keep the friends as a set
You current have just a single value for the friends property. As you start building the app you will need to store multiple friends. The most common is to then store an array or list of UIDS:
[ UID1, UID2, UID3 ]
Or
{
"-K.......1": "UID1"
"-K.......5": "UID2"
"-K.......9": "UID3"
}
These are unfortunately the wrong type for this data structure. Both the array and the second collection are lists: an ordered collection of (potentially) non-unique values. But a collection of friends doesn't have to be ordered, it has to be unique. I'm either in the collection or I'm not in there, I can't be in there multiple times and the order typically doesn't matter. That's why you often end up looking for friends.contains("UID1") or ref.orderByValue().equalTo("UID1") operations with the above models.
A much better model is to store the data as a set. A set is a collection of unordered values, which have to be unique. Perfect for a collection of friends. To store that in Firebase, we use the UID as the key of the collection. And since we can't store a key without a value, we use true as the dummy value.
So this leads to this data model:
{
users:{
UID:{
nickname: hello
}
UID2:{
nickname: world
}
}
friends:{
UID:{
UID2: true
}
UID2:{
UID: true
}
}
}
There is a lot more to say/learn about NoSQL data modeling in general and Firebase specifically. To learn about that, I recommend reading NoSQL data modeling and watching Firebase for SQL developers.
I keep a collection of Friends where the users field is an array of 2 user ids: ['user1', 'user2'].
Getting the friends of a user is easy:
friendsCollection.where("users", "array-contains", "user1").get()
This should get you all documents where user1 appears.
Now the tricky part was on how to query a single friend. Ideally, firebase would support multiple values in array-contains, but they won't do that: https://github.com/firebase/firebase-js-sdk/issues/1169
So they way I get around this is to normalize the users list before adding the document. Basically I'm utilizing JS' truthiness to check what userId is greater, and which is smaller, and then making a list in that order.
when adding a friend:
const user1 = sentBy > sentTo ? sentBy : sentTo
const user2 = sentBy > sentTo ? sentTo : sentBy
const friends = { users: [user1, user2] }
await friendsCollection.add(friends)
This basically ensures that whoever is part of the friendship will always be listed in the same order, so when querying, you can just:
await friendsCollection.where("users", "==", [user1, user2]).get()
This obviously only works because I trust the list will always have 2 items, and trust that the JS truthiness will work deterministically, but it's a great solution for this specific problem.

Field Level Permission in Spring Domain Object. View and Edit permission based filtering of object

I am looking for a spring based solution for this problem. I have solved this in crude way but looking for better solution.
I have a client server architecture application.
Based on user permission, I am able to :
get list of fields for loggedin user which he is not permitted to write.
get list of fields for loggedin user which he is not permitted to read.
Now, how can I verify that the object to be written into database is as per user permission in an efficient way. I can iterate over fields, check if its value is different from that stored in db and reject accordingly. Is there any effecient way ?
Example:
One domain entity "Account" which is stored in MongoDB.
class Account {
String name;
String email;
String mobile;
}
Corresponding DTO Object to be returned to client
class AccountDto {
String name;
String email;
String mobile;
}
Two User -> User A, User B
Scenario:
User A can edit [ name ] but not email, mobile.
User A can view [name, email] but not mobile.
How can I design to return only those field which he is permitted to view. I donot want to create numerous DTO based on every user permission.
How can I write a code to check that the Object to be written to database is valid as per permission assigned to loggedin user. I dont want to iterate over fields and check field permission and then discard. Expensive operation.
My solution: Whenever user is going to write to db, I can fetch the existing record , compare with the record he is going to write and reject if field value is changed if he has not that permission. But this adds DB read cost and is not that generic solution.

Eloquent Table Relationships

Hello i just realized how very confused i am by these relations, I have a question i need to ask. Assuming i have two table with records.
Roles
Administrator
Manager
Employee
Users
User 1
User 2
User 3
Now i want to create a relationship between these two tables, in this situation each user can have only one role but how do i express this relation?
To be more specific is it the user row in the table that can have only one role or the users table as a whole?
If it is the users table as a whole that can have only one role then in a situation where User 1 and User 2 are both administrators will the relationship then become many to many?
You might start by reviewing the documentation on relationships in Laravel/Eloquent: http://laravel.com/docs/5.1/eloquent-relationships
Your classes will look something like this:
class User extends Model
{
public function role()
{
return $this->hasOne('App\Role');
}
}
class Role extends Model
{
}
This means that each User has one Role - it doesn't prevent the same role from belonging to multiple users.
I seems it will become.
Role model
public function users()
{
return $this->hasMany('App\User');
}
User model
public function role()
{
return $this->belongsTo('App\Role');
}
so means, a Role can have many users and a user belongs to a role.
so User1 and User2 can be both Administrators. Check out laracast for additional info on relationship
I think, will be better, to use ManyToMany in Role-User reations, because, if you want now to use one role for one user, in future, probably, you will need to user more than one role to user. Also, ManyToMany not slower, than One-to-Many, but it more powerfull decision.
Role model
public function users()
{
return $this->belongsToMany('App\User');
}
User model
public function role()
{
return $this->belongsToMany('App\Role');
}

In hibernate how to set status for various table objects

I have two objects, Customer and Store. I would like a user (from a user table) to be able to specify a customer or store as "preferred". I would then be able to see a list of users who prefer different stores or customers. Is this possible with a hibernate mapping?
What would the table structure look if a status of preferred could be set on either customer of store per user?
So, a User has many preferred Stores, and a Store is the preferred store of many users. This is thus a ManyToMany association between User and Store.
Just map it as explained in the documentation:
public class User {
#ManyToMany
private Set<Store> preferredStores = new HashSet<Store>(0);
}
public class Store {
// necessary only if you want the association to be bidirectional:
#ManyToMany(mappedBy = "preferredStores")
private Set<User> preferringUsers = new HashSet<User>(0);
}