【发布时间】:2015-11-03 01:05:17
【问题描述】:
我正在用 Rails + MySQL 编写一个小应用程序,让人们互相发送电子邮件。 为了组织电子邮件,我引入了标签。
我的表格看起来像:
用户
- 姓名
消息
- sender_id(发给用户)
- 主题
- 身体
messages_users
- recipient_id(发给用户)
- message_id(转至消息)
标签
- user_id(fk 到用户,可为空)
- 姓名
为了让人们将标签应用到他们的消息中,我可以介绍这两个联合表之一:
labels_messages_users:
- messages_users_id(转至messages_users)
- label_id(转至标签)
labels_messages
- message_id(转至消息)
- label_id(转至标签)
- user_id(发给用户)
请注意,标签也不一定由用户创建。所以labels_messages表中的user_id列是必须的。
我不喜欢这种设计。太复杂了,联表太多了。一定有更优雅的设计。
我想到了这些解决方案:
解决方案 #1
消息
- recipient_id(发给用户)
- 我
- 主题
- 身体
- sender_id(发给用户)
labels_messages
- label_id(转至标签)
- message_id(转至消息)
标签 - user_id (fk to users) - 名称
优点:我喜欢这个解决方案,因为它看起来更像一个邮箱系统。简单得多。另外,按标签查询消息更高效。
缺点:我会在收件人和发件人之间重复主题和正文。 (顺便问一下GMail是怎么处理这个案子的……)
解决方案 #2
消息
- recipient_id(发给用户)
- 我
- sender_id(发给用户)
- message_content_id(转至 message_contents)
message_contents
- 主题
- 身体
labels_messages
- label_id(转至标签)
- message_id(转至消息)
标签
- user_id(fk 到用户,可为空)
- 姓名
优点:不再有内容重复。耶!
缺点:设计似乎是错误的。如何决定在messages和message_content之间设置fk的位置?他们都互相依赖。
解决方案 #3
消息
- sender_id(发给用户)
- 主题
- 身体
mail_items
- recipient_id(发给用户)
- message_id(转至消息)
labels_mail_items
- mail_item_id(转至 mail_items)
- label_id(转至标签)
标签
- user_id(fk 到用户,可为空)
- 姓名
优点:mail_items 不再是一个联合表(所以我可以在我的应用程序中引入一个新模型)
缺点:实际上仍在搜索...
你能帮我想出一个更好的解决方案吗? IT 领域的大佬(如 yahoo mail、gmail 等)如何处理这个问题?
谢谢!
编辑:添加标签表并说明如何将消息映射到标签。
【问题讨论】:
-
在您的解决方案 1 中,数据库级别没有数据重复。它只与 fk 一起存储一次。尽管您在用户为其创建标签的标签中缺少用户的 fk。虽然问题是是否可以有多个收件人,在这种情况下,您需要第二个收件人表。
-
> 它只与 fk 一起存储一次。你的意思是?此表中将多 N+1 行(N 为收件人数)。
标签: mysql ruby-on-rails database database-design