参照QQ邮箱,设计一款简易版的站内信

在学习软件编程的第一天,老师就告诉我们:程序 = 数据结构 + 算法。在使用一款应用时,我们只能看到页面上展示的内容,并不知道其背后的数据结构,更不知道使用了什么算法。

在写程序时,其实涉及到两种数据结构,一种是程序运行时,数据在内存里的存储结构,这和使用的开发语言有关;另一种是数据存放在数据库里的数据结构,和数据库有关,也和数据表设计有关。

这里所说的数据结构,是存储在数据库里的数据结构,现在用的数据库大部分都是关系型数据库。现在,要做一个类似于QQ邮箱的站内信,该如何设计呢?

简要描述一下站内信的业务需求:

  1. 发送邮件给一个用户或多个用户;
  2. 接收到邮件后,可以回复邮件;
  3. 可以对一封邮件溯源,查看一封邮件的历史往返记录;
  4. 对邮件的状态进行标注,未读的、已读的、已发送的;
    备注说明:发生邮件和回复邮件均可以上传图片,最多五个;每个用户可以清楚地看到未读、已读、已发送邮件列表;

发送邮件是需要邮箱服务器发送的,这里的应用场景是站内信,那么站内信的系统就可以充当邮箱服务器的功能。

首先看看,在QQ邮箱上创建一封邮件时,页面上需要哪些元素:


在邮件创建页面,大致需要以下这些字段属性:
1)接收人
2)邮件标题
3)邮件正文
4)附件
5)发送人,默认当前登录用户

接下来,开始设计主表,站内信信息表的初步的设计如下图所示:


只有站内信一个主表貌似不够用,接收邮件的用户,有可能是一个,也有可能是多个;接收人有的查看了邮件,有的还没有查看邮件;那么每个接收人对邮件的阅读状态可就不一样了,这个该怎么处理呢?

邮件的发送人,只有一个,这个是可以保证不变的,那么邮件的发送人就可以作为邮件信息表的字段来存储。接收人是多个,每个人的阅读状态又不同,那么这个可以单独设计为一个表,每个接收人作为一条独立的记录存在;其关系图如下所示。

站内信和发件人的关系,一个站内信只能有一个发件人;一个用户却可以发送多封邮件;站内信和用户是多对一的关系;
站内信和收件人的关系,一个站内信可能有一个或一个以上的接收人;一个用户是多个站内信的接收人;站内信和收件人,是多对多的关系;
每个接收人所接收的邮件默认为未读状态,在用户读过之后,变成已读状态,不会影响其他用户邮件的阅读状态。

那么有人会看到,邮件里漏掉了附件这个字段呀?

是的,没错,邮件里没有附件,为何没有附件?

因为附件有可能上传多个,虽然也有数量限制,但是你想,如果把这个字段放在主表里,最多限制五个,你就需要在主表里加入五个附件的字段,不管用户有没有上传五个附件,都需要数据库把这个空间开辟出来空在那里,这是资源浪费呀。

没错,这里会把附件最为一个单独的表来设计,作为一个附属表来设计,附属于邮件信息这个主表;

这样设计附件好处很明显,用户上传一个附件,增加一个附件的存储空间,没有上传过附件,就不需要开辟多余的空间。
一封邮件可能有零个或多个附件,一个附件只属于一封站内信,站内信和附件是一对多的关系。

接下来还有一个问题需要解决,如何追踪一封邮件的历史往返记录,就像QQ邮箱一样?

这个也好办,一封邮件可以有零个或一个父邮件,第一次创建的邮件是没有父邮件的,每次被回复的邮件都有一个父邮件;并且,一个邮件就只能有一个父邮件;在查看一封邮件的时候,就可以根据它的父邮件往上追踪过往的邮件,其设计图如下所示:


接下来把这个CDM设计图转化为PDM设计图,看看数据结构是不是我们想要的样子,关系上对应的对不对!



把主表中冲突的email_uid改为父email_uid,主表中的用户uid指向发件人,附件表的邮件uid指向主表的邮件uid,邮件与收件人的关联关系表分别指向邮件和用户,关联关系没有错,非常完美。

接下来,再做一点特殊的需求,每个用户都有所属企业,用户不仅可以给用户发邮件,也可以给某一个企业或多个企业发邮件,还可以发给全部的用户;如果是给某个企业发送的邮件,那么这个企业下的所有用户都能接收到,这个该如何设计呢?

先增加企业表的设计,再关联一下企业与用户的关系,一个企业下面可能有多个用户,一个用户只能属于一家企业,企业与用户是一对多的关系,如下图所示:


由于邮件的接收者可以是企业,所以在主表中增加一个冗余字段,用于标识这个邮件是发给企业的,还是发给企业下的某个人,还是发送给全部用户;在主表中增加一个接收人类型,默认0,默认0,0:全部,1:企业,2:用户,如下图所示:


接收者这边该如何处理呢?

同样地,也在关系表中增加企业的唯一标识符做关联,如果是发送给企业的,那么接收人那一列空着,当企业下的用户登录时,将能看到发送给这个企业的邮件,该用户阅读完毕后,再往关系表中增加一条已读的记录,如下图所示:


最终的PDM图

也就是说,站内信发给所有用户的时候,是不需要填充关系表的,只需要根据主表的接收者类型来判断,接收者类型为0又不是自己发送的,则处于未阅读状态。

如果接收人是一个或多个企业,那么只会在关系表中新增站内信和企业的关联关系,企业用户登录后,也根据接收者类型和企业uid来获取未读的邮件。

如果接收人是一个或多个用户,那么就会在关系表中新增站内信和接收者的未读状态的关联关系,用户登录后,根据接收者类型和未读状态来获取未读邮件。

未读邮件的检索最复杂,需要三种复合条件的判断。

已读邮件就比较简单了,主表关联关系表,状态为已读的,就是已读的数据。

已发送邮件最简单,根据发送人检索便可。

在查看某一封邮件,根据父类邮件uid去获取上一封邮件,有父类邮件uid就递归获取,直到父类uid没有为止,无意中发现是这样有意思的一个图:


作为一款简单的站内信设计,相信这些功能已经足够用了,不够用再加吧,哈哈。临需而变哟~!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,794评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,050评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,587评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,861评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,901评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,898评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,832评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,617评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,077评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,349评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,483评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,199评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,824评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,442评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,632评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,474评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,393评论 2 352

推荐阅读更多精彩内容