MongoDB的数据建模

MongoDB是一种面向Document的NoSQL数据库,如果我们还是按照RDB的方式来思考MongoDB的数据建模,则不能有效地利用MongoDB的优势;然而,我们也不能因为Document的灵活性,就可以在设计之初放任自流。

适度的建模是非常有必要的,尤其对于相对复杂的关联关系。因为在MongoDB中,处理这种关联关系既可以使用Link,也可以使用Embedded。

我们要评价一种决策,不能将其与具体的上下文割裂开来做判断,那种单纯说A技术要比B技术好的做法,就像小孩子看卡通片里的人物只知道说谁是好人谁是坏人一般的幼稚。世界上没有一种***至善的技术,关键还是要结合场景来看使用是否得法。

例如使用Embedded方式,就各有优缺点。举例来说,倘若我们采用Embedded方式将Addresses作为Person对象内部的数组:

 
 
 
 
  1. {
  2.   name: 'Kate Monster',
  3.   ssn: '123-456-7890',
  4.   addresses : [
  5.      { street: '123 Sesame St', city: 'Anytown', cc: 'USA' },
  6.      { street: '123 Avenue Q', city: 'New York', cc: 'USA' }
  7.   ]
  8. }

当我们在查询Person的信息时,要获取其内嵌的属性细节,我们无需再执行多次查询。倘若我们改变一下领域场景,需要开发一个任务跟踪系统。如果我们将Tasks的信息嵌入到Person对象中,当我们面对以下需求:

  • 显示所有明天到期的任务
  • 显示所有未完成的任务

采用这种Embedded就不那么令人愉快了。

如果采用Link方式,情况就完全不同了:

 
 
 
 
  1. //Tasks
  2. [
  3.     {
  4.         _id: ObjectID('AAAA'),
  5.         task_number: 1234,
  6.         taks_name: 'Prepare MongoDB environment',
  7.         due_date: '2017-01-15'
  8.     },
  9.     {
  10.         _id: ObjectID('BBBB'),
  11.         task_number: 1235,
  12.         taks_name: 'Import Test Data',
  13.         due_date: '2017-02-15'
  14.     },
  15. ]
  16. //Persons
  17. {
  18.   name: 'Kate Monster',
  19.   role: 'Manager',
  20.   tasks : [
  21.     ObjectID('AAAA'),
  22.     ObjectID('BBBB')
  23.   ]
  24. }

有得必有失,当我们需要查询Person承担的Tasks时,采用这种方式,就需要采用application-level join方式执行两次查询。

这种建模方式还带来另一种可能,就是原本Person->Tasks的one-to-N关系就可以变为N-to-N关系,因为一个Task可以被多个Person所拥有。如果采用Embedded方式,则会导致Task数据的冗余。

在文章 6 Rules of Thumb for MongoDB Schema Design中,作者将这种1对N关联实现的判断依据划分为三种形式:

  • one-to-few
  • one-to-many
  • one-to-squillions

但我认为该怎么实现关联,应该从Entity之间的领域关系来判断,我们可以引入DDD的Aggregation设计概念作为建模的依据。简单来说,如果使用Embedded,可以认为该Entity处于Aggregation边界之内,对外应该通过Aggregation Root来访问。文章 6 Rules of Thumb for MongoDB Schema Design的说法就是:

Will the entities on the “N” side of the One-to-N ever need to stand alone?

如果是Stand Alone,就意味着该Entity可以成为一个独立的Aggregation,然后再通过ID与另外一个Aggregate关联。

在SegmentFault上则有人做了如此总结:

  • FirstClass (比如“User”这种) 应该用独立的Collection
  • "条目类型"的,应该 embedded
  • 两个模型之间如果是包含关系,用 embedded
  • 多对多关系,用 link(类似sql里面的foregin key)
  • 如果一个模型,其可能存的对象很少,那么就用独立的collection,这样有助于mongodb server做缓存
  • embedded方式不利于做复杂的关联,复杂的查询
  • embedded方式性能很有优势,如果你有“性能”方面的要求,可以考虑用embbed

【本文为专栏作者“张逸”原创稿件,转载请联系原作者】

网站题目:MongoDB的数据建模
本文路径:http://www.shufengxianlan.com/qtweb/news23/378223.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联