I'm working on a pong game app : a match can be played by two user, and i want to store, per user, metadata information like what was the XP of the player before the match, how many times the user managed to catch the ball, etc...
Being fairly new to relational database and Prisma, i'm still wondering what should be the ideal relationship between my models, that could give me flexibility, and expressiveness to the schema file.
This is what i did so far :
model User {
id Int #id #unique #default(autoincrement())
login String #unique
name String #unique
// [...]
matchPlayed PlayerMatch[]
}
// [...]
model PlayerMatch {
user User #relation(fields: [userId], references: [id])
userId Int
Match Match #relation(fields: [matchId], references: [id])
matchId Int
xpAtBeginning Int
winner Boolean?
xpAtEnd Int?
bounces Int?
score Int?
##id([userId, matchId])
}
model Match {
id Int #id #unique #default(autoincrement())
createdAt DateTime #default(now())
finishedAt DateTime?
players PlayerMatch[]
}
But for me, that doesn't sound right. I know explicit many-to-many relationships are used when you need to store metadata about the relation, that seems fair : but only two player can play in a match, and here, the field players indicates that we can have more than two players.
Is there a better way to achieve what i want to do ?
Thanks.
Related
Given the following prisma model:
model User {
user_id String #id #default(uuid())
groups Group[] #relation("CreatedGroups")
participating_groups Group[] #relation("Participants") // -- keep track!
}
model Group {
group_id String #id #default(uuid())
participants User[] #relation("Participants") // -- keep track too!
creator_id String
creator User #relation("CreatedGroups", fields: [creator_id], references: [user_id])
}
Say i needed to add one participant into a group. By doing so, i'm updating 2 things:
The participants array in the Group model. (connecting the user)
The participating_groups array in the User model. (connecting the group)
Notice i've set a #relation at each field to mention it's related opposite at the other model.
My question is, how do i implement that in one single query, instead of updating both models seperately?
UPDATE 09/06/2018
My models looks like this:
public class Activity
{
public int Id { get; set; }
public List<Additive> Additives { get; set; }
}
public class Additive
{
public int Id { get; set; }
public int ActivityId { get; set; }
public Activity Activity { get; set; }
}
Original Question
I'm developing a RESTful API and i want to do it the cleanest way possible.
Currently i'm working on data retrieving. So i got this
If i create a new resource called activity and it has an array of objects, lets say (hardcoded, not representative):
{
"name": "act1",
"objects": [
{ "obj1":"val1" },
{ "obj2":"val2" }]
}
I'll could add or delete objects from my array.
Now, my question is, if i want to access them with an url like this:
Api/activity/1/objects/2
Which is the correct way to tell MySQL that this object is my 2th object of the list?
Or maybe i should select ALL objects of Act1 on the backend and filter them to retrieve just the 2th one.
It's pretty important that resources in your REST service have stable urls. So to figure out what 'second' is, you really need to think about what it means to be second in the list.
Are you ordering by something? If so, it's probably a bad idea to use this structure because adding a new entry can change the order and what was 'second' before might no longer be in the future.
The best thing you can do is add some kind of new id for these entries so accessing a specific resource by uri will always return that resource (or 404, etc).
I finally found the answer i were looking for.
mysql two column primary key with auto-increment
This is a MyISAM engine feature.
For MyISAM and BDB tables you can specify AUTO_INCREMENT on a secondary column in a multiple-column index. In this case, the generated value for the AUTO_INCREMENT column is calculated as MAX(auto_increment_column) + 1 WHERE prefix=given-prefix. This is useful when you want to put data into ordered groups.
In my case, this query does the job
CREATE TABLE additive (
id INT NOT NULL AUTO_INCREMENT,
activity_id INT NOT NULL,
other_column VARCHAR(30) NOT NULL,
PRIMARY KEY (activity_id, id)
) ENGINE=MyISAM;
I've been trying for a while to understand how GORM works, and I think I've got it down. However, I'm having a heck of a time getting my relationships correct.
Here is my database schema setup (2 tables):
Table - Users
userhash varchar(255)
firstname varchar(255)
lastname varchar(255)
Table - Logs
userhash varchar(255)
accessdate date
There are no foreign key and primary key constraints defined in the tables. However, in the users table the userhash will be unique. I didn't design it this way, but I have to use it like this.
Now for my Grails domain classes:
Class - Users
class Users {
String userhash;
String firstname;
String lastname;
static hasMany = [logs: Logs]
}
Class - Logs
class Logs {
String userhash;
Date accessdate;
static belongsTo = Users;
}
In my controller, I do the following:
def user = Users.findByUserhash("nraboy");
println user.firstname;
println user.logs;
It prints out the correct firstname, but when I try to display the logs, it is null or empty. Am I requesting the data incorrectly for child tables or am I missing something somewhere in the domain class design?
I've tried to do the following, but had now luck as well:
Class - Logs
static mapping = {
id generator: "assigned", name: "userhash", type: "string"
}
Class - Users
static mapping = {
userhash generator: "foreign"
}
I figured the above would let me manually define the primary key and foreign key via code since it didn't exist int he tables. No luck though.
Any help would be appreciated.
Thanks,
It looks like you may have to do something with in Users for the logs association to force the foreign key to be in the Logs table, as it is. See the GORM docs One-to-Many Mapping section. Perhaps something like:
static hasMany = [logs: Logs]
static mapping = {
logs column: 'userhash'
}
I would be curious to hear if this worked...
First off, I am not a DBA, I am a C# developer. I am working on a pretty complex web application and I want to start with a solid database. So here is my issue:
I am trying to create a Settings table that will hold settings for multiple objects. ie: User settings, Season settings, League settings, Team settings.
Instead of creating a table for each of those I would like to keep everything in the Settings table but I can't figure out how to create the foreign key.
My approach is to have three columns in the Settings table: TableName PrimaryKey ID. These three columns would create a composite key that would reference the appropriate object. Is my approach considered bad practice or am I on the right track? Is there a way I can do this that will still work with entity framework?
Here is my way of handling this.
In this diagram, ConfigId is primary key which is used as an FK in Person table as EyeColor, BloodType, PersonType and many more. These columns also hold a Check constraint to ensure no value apart from eye color or corresponding column get stored based on ConfigType. However this comes at a cost of broader datatype which may be smallint or int instead of tinyint.
Only difference is, I am calling these settings as ConfigType in your case {User, Team, Season etc.} and any extension can be done by inheritance concept by creating another table using ConfigId as FK in child table.
If you use inheritance, by default EF will use one table for the entire hierarchy. This is known as Table Per Hierarchy or TPH
public abstract class Setting
{
public string Key { get; set; }
public string Value { get; set; }
}
public class UserSetting : Setting
{
public int UserId { get; set; }
public virtual User User { get; set; }
}
public class SeasonSetting : Setting
{
public int SeasonId { get; set; }
public virtual Season Season { get; set; }
}
I have a Class which looks something like this:
public class User {
public virtual int ID;
public virtual string Name;
public virtual IList<int> userRights;
}
I want to make a UserMap : ClassMap<User>
Mapping the name is no problem however i cant seem to figure out how to map the userRights.
Table looks like
UserTable
User_id int
User_Name nvarchar
User_group int
UserRights
User_group int
RightID int
How would you map this ?
Well if you want a List you need an index. So I would recommend just making it an ICollection unless the ordering is significant.
The mapping should look something like:
HasMany(x=> x.userRights).Element("RightID").AsBag();
However, upon looking at your tables, I noticed something odd. You're trying to use a one-to-many without having the primary key in the User_Rights table. If you had User_Id in UserRights the above should work.
Otherwise it looks like there's a UserGroup, which should be modeled by your classes.