Reputation: 175
I just seek for an advice, what is the best way to a create nice and elegant relationship (that could be used with ORM methods). The content of the database looks like this:
mysql> describe books;
+--------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| title | varchar(45) | YES | MUL | NULL | |
| author | varchar(45) | YES | | NULL | |
| cover | varchar(45) | YES | | NULL | |
+--------+-------------+------+-----+---------+----------------+
mysql> describe users;
+----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| username | varchar(45) | YES | | NULL | |
+----------+-------------+------+-----+---------+----------------+
mysql> describe users_books;
+---------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+---------+------+-----+---------+-------+
| user_id | int(11) | YES | | NULL | |
| book_id | int(11) | YES | | NULL | |
+---------+---------+------+-----+---------+-------+
mysql> describe comments;
+---------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| body | varchar(45) | YES | | NULL | |
| rate | varchar(45) | YES | | NULL | |
| user_id | int(11) | YES | | NULL | |
+---------+-------------+------+-----+---------+----------------+
mysql> describe books_comments;
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| book_id | int(11) | YES | | NULL | |
| comment_id | varchar(45) | YES | | NULL | |
+------------+-------------+------+-----+---------+-------+
I don't have any issues with that model, but I think it can be improved. In this way I am fetching the records:
select body, rate, users.username,title, author from users
inner join users_books on users.id = users_books.user_id
inner join books on books.id = users_books.book_id
inner join books_comments on users_books.book_id = books_comments.book_id
inner join comments on books_comments.comment_id = comments.id
where users.id = 1 and comments.user_id = 1;
While users can have many books, a comment is very specific for a book owned by a specific user. I think that is the point I am not getting it the right way.
Upvotes: 0
Views: 128
Reputation: 29759
Your current structure suggests that a single comment may be about several books (book_comments
is a junction table).
But what you want is:
a comment is very specific for a book owned by a specific user
A "book owned by a user" is nothing else but an entry in the users_books
table. Drop books_comments
. Add to comments
a foreign key to users_books
' primary key, i.e. (user_id, book_id)
.
I would create your comments
table like this:
CREATE TABLE comments (
user_id INT NOT NULL,
book_id INT NOT NULL,
-- more fields here
PRIMARY KEY (user_id, book_id)
FOREIGN KEY (user_id, book_id) REFERENCES users_books (user_id, book_id)
);
This structure assumes that a comment may be posted by a user only on a book that she owns (user_id
would be both the book owner and the comment author).
You can add a second foreign key reference to user
(e.g. a author_id
) to allow any user (author_id
) to post a comment on any book (book_id
) owned by someone in particular (user_id
).
Upvotes: 1