I am creating an online blog website and for each blog post, I'd like to have the user be able to create/edit/delete their own category so that they may categorize their post.
What is generally considered a good database design for user generated categories?
This is my proposed table design. (Is there a name for this type of db?)
USER_TABLE
user_id (pk), user_name
CATEGORY_TABLE
category_id (pk), category_name
USER_CATEGORIES
user_id (fk), category_id (fk)
Thanks for helping out. I'm confident there's a post somewhere regarding this but I was unable to find it. If this is a dupe please let me know and I will remove this question.
This is a many to many relationship. This would allow each user to potentially have many different categories and each category to potentially have many different users. This seems like a useful model for what you are trying to do.
I think your schema looks good. You are keeping the category labels in one table to avoid duplication and then just assigning their IDs to the users.
If what you are trying to do is to have "private" categories for each user then this is fine.
If on the other hand categories are supposed to be public (sth like tags on stackoverflow) then you may consider another option - not storing user<->category relationship, instead add field use_counter to category table and use triggers to increment it when category is being used(blog entry is categorized) or decrement when it's "freed" (blog entry is deleted/ its category is removed). When the use_counter reaches 0 - remove the category.
Related
I read similar question (Relational table naming convention), but unfortunately I couldn't find the answer for my problem.
I have products. Products can have images and comments. They are one-to-many relationships.
The table and entity names are the following:
product (Product)
product_comment (ProductComment)
product_image (ProductImage)
Product is independent, comment and image depends on product. No problems so far.
But i need to classify products into categories (one-to-many).
Category can exist on its own, it's independent, so i can't use the product_category (ProductCategory) naming (it would express that products can have categories).
The naming without any prefix (category (Category)) is also not good, because there could be other categories in the database (categories for users etc.).
So it seems for me that the only solution is:
category (Category)
category_product (CategoryProduct)
category_product_Comment (CategoryProductComment)
category_product_Image (CategoryProductImage)
But I'm not happy with that either. It expresses that categories can have products...
Any help is highly appreciated!
Thank you!
A little late but perhaps can help someone else struggling with naming...
It might help to think of the table/entity names independent of the actual database relationships. If this "type" of category is only for products then it is a "product category" in the real world and thus it would make sense to name the table product_category. If you have a category type for users then what you have is a "user category" and the logical table name would be user_category. The same holds true for your product images and comments.
So, when naming an entity, try to think about what the entity is rather than how it relates to other entities.
In the laravel docu is the following example for has-many-through relationship: Country has many posts through user.
But in my case i need something like this:
User has many roles through customer.
I would like to have the has-many-through relationship from user to role.
Is there a way to get it working this way?
EDIT
I solved my problem with a collection method:
public function roles() {
$roles = $this->hasMany('SC\Customer')->get()->each(function($item) {
return $item->role();
});
return $roles;
}
It all depends on what you're trying to accomplish.
In most cases where someone needs to define roles, creating a separate pivot table that joins tables would be a good way to do it.
Luckily, Laravel's documentation covers this pretty well, you will likely find the answer in this section: http://laravel.com/docs/5.1/eloquent-relationships#many-to-many
Keep reading through that section and all the way down, Taylor goes deeper into the subject and various solutions for different scenarios..
Let's say you have many users and many roles (admin, user, moderator) etc. Many of these users can have different roles and perhaps other attributes, such as if they are a customer or not. You start by creating the user, roles tables (or whatever else needed).
You can then create a joining pivot table, let's say role_user. In it, you can specify foreign keys like user_id which represents id from the user table and role_id which represents id from the role table.
By specifying the foreign keys, you attach a user to a role and then to whatever attribute you would like in another column. So if you have another column in the pivot table that is "customer", which can 1/0 (is customer / is not customer) or maybe you want to add another foreign key which can be customer_id that represents id column in a customer table.
It all depends on what you're trying to accomplish, but it's easy to get snowed in. Using a UML software to model it all out before actually coding to get a abstract overview, could be a good idea. I would recommend StarUML.
Then in your User model you can just bind them by specifying the relationships, something like this:
return $this->belongsToMany('App\Role')->withPivot('column1', 'column2');
I have an app where users can log comments related to any specific entity that the system has and I wanted to know if there is a "best practice" way to handle the design of the db for this kind of feature.
For example: Three current entities (tables) deal are Question, Documentation, ReferenceMaterial (self explanatory what each hold). The user can leave a comment on any one of those particular items and all comments are simply a varchar field, user id, and date of comment. EDIT: Comments can also belong to more than one entity. For example, all Question entities belong to a Quiz or Test entity. Each of those (Quiz and Test), can also have comments associated with themselves. So you could run a report to see all comments left for a test and easily just query the Comment table for every record with that test foreign key, or you could limit your query to just the comments left for questions in that test, or a particular question itself. It offered a lot of flexibility END EDIT
Right now the way that I hvae this is one Comment table with a foreign key relationship with each of the other entity tables (i.e. fkQuestion, fkDocumentation, fkReferenceMaterial, etc). So all comments in the system are stored in this table and based on what page the user is on, I conduct the join to that particular entity's records.
Is there a best practice way of doing this?
Thanks in advance for any help.
So I know the convention for naming M-M relationship tables in SQL is to have something like so:
For tables User and Data the relationship table would be called
UserData
User_Data
or something similar (from here)
What happens then if you need to have multiple relationships between User and Data, representing each in its own table? I have a site I'm working on where I have two primary items and multiple independent M-M relationships between them. I know I could just use a single relationship table and have a field which determines the relationship type, but I'm not sure whether this is a good solution. Assuming I don't go that route, what naming convention should I follow to work around my original problem?
To make it more clear, say my site is an auction site (it isn't but the principle is similar). I have registered users and I have items, a user does not have to be registered to post an item but they do need to be to do anything else. I have table User which has info on registered users and Items which has info on posted items. Now a user can bid on an item, but they can also report a item (spam, etc.), both of these are M-M relationships. All that happens when either event occurs is that an email is generated, in my scenario I have no reason to keep track of the actual "report" or "bid" other than to know who bid/reported on what.
I think you should name tables after their function. Lets say we have Cars and People tables. Car has owners and car has assigned drivers. Driver can have more than one car. One of the tables you could call CarsDrivers, second CarsOwners.
EDIT
In your situation I think you should have two tables: AuctionsBids and AuctionsReports. I believe that report requires additional dictinary (spam, illegal item,...) and bid requires other parameters like price, bid date. So having two tables is justified. You will propably be more often accessing bids than reports. Sending email will be slightly more complicated then when this data is stored in one table, but it is not really a big problem.
I don't really see this as a true M-M mapping table. Those usually are JUST a mapping. From your example most of these will have additional information as well. For example, a table of bids, which would have a User and an Item, will probably have info on what the bid was, when it was placed, etc. I would call this table... wait for it... Bids.
For reporting items you might want what was offensive about it, when it was placed, etc. Call this table OffenseReports or something.
You can name tables whatever you want. I would just name them something that makes sense. I think the convention of naming them Table1Table2 is just because sometimes the relationships don't make alot of sense to an outside observer.
There's no official or unofficial convention on relations or tables names. You can name them as you want, the way you like.
If you have multiple user_data relationships with the same keys that makes absolutely no sense. If you have different keys, name the relation in a descriptive way like: stores_products_manufacturers or stores_products_paymentMethods
I think you're only confused because the join tables are currently simple. Once you add more information, I think it will be obvious that you should append a functional suffix. For example:
Table User
UserID
EmailAddress
Table Item
ItemID
ItemDescription
Table UserItem_SpamReport
UserID
ItemID
ReportDate
Table UserItem_Post
UserID -- can be (NULL, -1, '', ...)
ItemID
PostDate
Table UserItem_Bid
UserId
ItemId
BidDate
BidAmount
Then the relation will have a Role. For instance a stock has 2 companies associated: an issuer and a buyer. The relationship is defined by the role the parent and child play to each other.
You could either put each role in a separate table that you name with the role (IE Stock_Issuer, Stock_Buyer etc, both have a relationship one - many to company - stock)
The stock example is pretty fixed, so two tables would be fine. When there are multiple types of relations possible and you can't foresee them now, normalizing it into a relationtype column would seem the better option.
This also depends on the quality of the developers having to work with your model. The column approach is a bit more abstract... but if they don't get it maybe they'd better stay away from databases altogether..
Both will work fine I guess.
Good luck, GJ
GJ
So, I'm building a website and I'm going to have standard CMS tables like Article, Blog, Poll, etc. I want to let users post comments to any of these items. So my question is, do I need to create separate comments tables for each (e.g. ArticleComment, BlogComment, PollComment), or can I just make a generic Comment table that could be used with any table? What has worked for people?
Method 1: Many Comment Tables
Article {ArticleID [PK], Title, FriendlyUrl}
ArticleComment {ArticleCommendID [PK], ArticleID [FK], Comment}
Blog {BlogID, Title, PubDate, Category}
BlogComment {BlogCommendID [PK], BlogID [FK], Comment}
Poll {PollID, Title, IsClosed}
PollComment {PollCommentID [PK], PollID [FK], Comment}
Method 2: Single Comment Table
Article {ArticleID [PK], Title, FriendlyUrl}
Blog {BlogID, Title, PubDate, Category}
Poll {PollID, Title, IsClosed}
Comment {CommentID [PK], ReferenceID [FK], Comment}
I'd go with the generic comment table. It will make a lot of things much simpler. I'd also tag comments with the ID of the user who created them, or other source-identifying information (IP address, etc.). Even if you don't display this it can be very handy when you have to clean up spam, etc.
There seem to be two major ways of mapping OO-inheritance to relational databases:
Take all the attributes from the parent class and all the child classes and put them in the table, together with a 'which class is this?' field. Each object is serialized as one row in one table.
Create one table for the parent class and one table for each child class. The table for the parent class table contains the 'which class is this?' field. The child class table contains a foreign key pointing to the parent class table. Each object is serialized as one row in the parent class table and one row in the child class table.
Method one doesn't really scale well: it quickly winds up with lots of nullable fields, almost always null, and scary CHECK constraints. But it is fairly simple for small class hierarchies.
Method two scales much better, but is more work. It also results in many more tables in your schema.
I suggest taking a look at method two for your Articles/Polls/Blogs tables — to me, they sound like child tables of a Content or something. You will then have a very clear and easy place to attach comments: to the Content.
Why do you want to keep all of your comments in the same table? Will you be treating all comments as a group? If you don't anticipate working with all of the comments on all items as a single group then there isn't really a reason to bunch them all together. Just because two entities in a database share the same attributes doesn't mean that they should be put in the same physical table.
I'd suggest just one comment table, adding an ItemID field telling which type of item is the comment for:
Article {ArticleID [PK], Title, FriendlyUrl}
Blog {BlogID, Title, PubDate, Category}
Poll {PollID, Title, IsClosed}
Comment {CommentID [PK], ReferenceID [FK], ItemID, Comment}
Item {ItemID, Type}
The last table would contain records such as (1, 'article'), (2, 'blog'), etc.
That way you'll be able to identify which content type each comment was made for.
I am working on a system where we used the following model for comments:
Data Table(s) Many-to-many Assoc Comment Table
CommentableId -> CommentableId/CommentId -> Comment_Id
Not my design, but I like the fexibility. It allows us to use one comment in many
different places. Since this is not trivial to implement in the UI, users don't get to see this feature (just a text box to type in a comment), but it is used when we do batch imports and legacy data processing in the database.