了解过小程序的人,肯定都知道小程序的云开发模式,不知道的现在应该知道了。
在用云开发来开发产品的时候,如果只是一些简单的应用,需要处理的数据不是很多,在云数据库中建几个collection
就能应付的那种,那么小程序的云开发文档已经足够了;但是如果想用云开发来开发一个复杂一点的产品,不对数据库进行一番设计是不行的。
今天要给大家介绍的是如何在云数据库当中设计1对多的关系,云数据库是一个非关系型数据库,对于这种1对多关系在项目中也是非常的常见,比如用户在外卖app里填的地址可能会有多个,这里的用户就是1,填的地址就是多;再比如我们在大学里选修课程,学生就是1,而所有的课程就是多;还有就是你现在看的这篇文章和评论的关系,一篇文章肯定会对应多条评论。这些都是一对多的关系,说起来很简单,但我们如何将这种关系在数据库当中展示或者设计出来呢?别急,慢慢来。
一对多的关系主要分为三种场景,其实我上面举的三个例子分别就是对应的三种不同的场景。有的人可能看不出三个例子有什么不同。别急,慢慢品。
对于例子一,“1”就是用户,“N”表示接收外卖的地址。用户的地址个数不会太多,一般就是公司一个地址,住的小区一个地址,实习生可能还有个学校宿舍的地址。对于这种“N”的数量不是很多的情况,我们可以创建一个User集合,然后将用户的所有地址放到用户的子集中,就像下面这样:
User集合
{
uid: 1,
addressList: [{...}, {...}, {...}],
...
}
{
uid: 2,
addressList: [{...}, {...}, {...}],
...
}
...
这是非常简单,非常方便的一种设计方式,查询的时候只需要遍历User集合一次就能拿到“1”的所有数据和“N”的所有数据了。
现在我们来看下第二个例子 - 学生选课,粗略一看,这和场景一没什么区别嘛,一个学生最多也就选择十几门课,完全可以将学生和课程都放在一个Student集合里,就像下面这样:
Student集合
...
{
studentId: 1,
courseList: [{courseId: 1, ...}, {courseId: 2, ...}, {courseId: 3, ...}, ...],
...
}
{
studentId: 2,
courseList: [{courseId: 4, ...}, {courseId: 5, ...}, {courseId: 6, ...}, ...],
...
}
...
但事情并没有这么简单,假设现在课程1的老师请假了,需要由另一位老师来代课,那么课程1里面老师相关的信息就需要同步地改成代课老师的信息,在上述设计模式下就需要遍历所有学生的课程数组,逐一地找到目标课程进行修改,更改的效率比较低。有没有更高效方式呢?答案是肯定的。第二种设计模式就是将学生和课程放在两个集合里,学生的课程列表里存放其所选课程的id,如下所示:
Student 集合
...
{
studentId: 1,
courseIdList: [1, 2, 3, ...],
...
}
{
studentId: 2,
courseIdList: [4, 5, 6, ...],
...
}
...
-------------------------------分割线---------------------------
Course 集合
...
{
courseId: 1,
courseName: "课程1",
teacherName: "老师1",
...
}
{
courseId: 2,
courseName: "课程2",
teacherName: "老师2",
...
}
...
现在当我们修改课程信息的时候只需要遍历一遍Course集合就可以了,这样设计还有其他的好处:学生在选课的时候需要查看所有的课程信息,我们只需要将Course集合里的数据全部返回给前端就可以了,如果采用第一种设计模式,我们还需要对数据进行非常复杂的过滤操作,处理逻辑非常地不自然,也并不高效。相较而言,第二种模式更加的高效和自然。但第二种设计模式也有缺点,缺点就是当我们查询一位学生所选的课程的时候我们需要遍历两个集合,首先需要遍历Student集合找到目标学生包含的课程id,然后遍历Course集合筛选出课程。
最后我们来看下第三种场景 - 文章评论,在这种场景里“1”代表文章,“N”代表评论。一篇文章的评论数是不受限制的,可以有很多。比如流量明星的一篇微博的评论数,破千上万那是基本操作。在这种“N”的数量级特别大的情况下,第一种设计模式显然不能被采用。目光投向第二种设计模式,成千上万的评论id被塞在一个数组里,看上去很不优雅,而且数组的长度是有限制的,不能存放太多。这时,一种适合此情此景的设计模式呼之欲出:
Article 集合
...
{
article: "文章1",
articleId: 1,
...
}
{
article: "文章2",
articleId: 2,
...
}
...
----------------------------------分割线-----------------------
Comment 集合
...
{
comment: '评论1',
commentId: 1,
articleId: 1,
...
}
{
comment: '评论2',
commentId: 2,
articleId: 1,
...
}
{
comment: '评论3',
commentId: 3,
articleId: 2,
...
}
上面的demo
就是模式三的基本结构,虽然模式二和模式三都是将“1”和“N”分在两个集合里,但是却有明显的不同。模式二是在“1”中保存了“N”的id
信息,而模式三是在“N”中保存了“1”的id
信息,可以看到在上面的Comment集合里,每条评论都有一个articleId
字段,表示该条评论属于这篇文章(articleId={articleId}的这篇文章)。属于同一篇文章的评论,它们的articleId
都是相同的。当所有的评论都放在一个集合里的时候,我们就可以通过articleId
来进行高效的筛选了。
好了以上就是数据库中1对N关系的三种设计模式,它们各有各的优点,在使用的时候需要结合实际的应用场景来选择合适的设计模式。