最近公司正在研发一个医疗行业的数据库,收录医疗创业公司,人,以及投资机构和医疗编辑们的知识,并将它们关联起来,以便后期的数据分析和编辑选题选素材。

  在这种需求下,我们选用了Mongodb这种介于nosql和关系型数据库之间的一种数据库,本质上Mongodb不能单纯的归类为非关系型,虽然他是nosql文档型数据库,但并不意味着它不能有关系,纯nosql数据库应该是Redis,memcached这类key-value数据库,Mongodb是一种特殊的nosql,它采用json的方式存储数据,操作和使用都非常灵活,没有关系型数据库严格的类型长度和复杂的查询,我们的需求对于一个字段来说希望他是灵活的,但是也希望它能处理一些关系,所以Mongodb最适合我们。

  传统关系型数据库在涉及一对多的情况下,通常会设置外键来关联,在涉及多对多的情况下,会采用中间表的方式。而Mongodb有个黑科技,因为它是以json存储的,所以,字段类型可以是Array,这样,就可以很方便的实现1 to n的情况,n to n也可以很方便的实现。

  下面就说一下Mongodb的几种建模方式,网上的帖子大都是以1 to n为例,这里我们就以最复杂的n to n来说

  1)内嵌文档

  比如每个Person会有多个Address, 同一个Address又会存在不同的Person中。


{
    name: 'Kate Monster1',
    _id: ObjectId('ABCD'),
    addresses : [
      { street: '123 Sesame St', city: 'Anytown', cc: 'USA' },
      { street: '123 Avenue Q', city: 'New York', cc: 'USA' }
    ]
  }
{
    name: 'Kate Monster2',
    _id: ObjectId('ABCE'),
    addresses : [
      { street: '123 Sesame St', city: 'Anytown', cc: 'USA' },
      { street: '123 haidian E', city: 'Beijing', cc: 'CHA' }
    ]
  }

 

  优点:一条语句就可以得到某个人的所有地址信息,查询效率无疑是最高的。



  缺点:无法像操作独立文档那样来操作地址信息。你必须首先操作Person文档后,才有可能继续操作Address,而且对于单条文档的大小会有影响。

  使用场景:不需要独立建表的信息,信息比较简单,数量很少,不值得单独做一个表,没有太多独立操作,但是又有n to n的需求(n < 100),n to n需要使用$elementMatch操作符来反向查询含有某条记录的所有记录。

  2)内嵌文档id和中间字段

  比如产品(Product)和零部件(part),每个产品会有很多个零部件,每个零部件又被用到了多个产品上,同一个零件在不同产品上的花费又是不一样的。

零部件(Part):
{
    _id : ObjectID('AAAA'),
    name : 'xxx',
    price: 3.99
}


{ _id : ObjectID('BBBB'), name : 'xxx2', price: 5.99 }

产品(Product): 
{
   _id : ObjectID('ZZZZ'),
    name : 'Knife1',
    parts : [
        { part_id: ObjectID('AAAA'), cost: 5 },  
        { part_id: ObjectID('BBBB'), cost: 7 }
    ]
}
{
   _id : ObjectID('YYYY'),
    name : 'Knife2',
    parts : [
        { part_id: ObjectID('AAAA'), cost: 8 }
    ]
}


  优点:部件是作为独立文档存在的,你可以对某一部件进行独立的操作,比如查询或更新,有效减小了单个文档的大小,并且可以实现中间表字段的功能。

  缺点:你必须通过两次查询才能找到某一个产品所属的所有部件详细信息,或者反向找到某个零件所属的所有产品。对文档的大小依然有压力。依然要通过产品来查询两种情况,除非你在零件表也建立一个Array,存放产品id,不过在更新关系字段的时候需要同时更新两边。

  使用场景:需要独立建表的信息,信息比较复杂,但数量不是太多,有很多独立操作,但是又有n to n的需求(n < 1000),这是一种最常见的用法

  3)完全按照关系型数据库的做法,建立外键(1 to n),或者建立中间表(n to n)

  这种方式就不再赘述了,如果过度使用这种办法,建议不要使用Mongodb,还是使用关系型数据库更好一些

  使用场景:信息关系极度复杂,数量巨大,有很多独立操作,又有n to n的需求(n > 1000)

  最后附上一个官方链接: http://blog.mongodb.org/post/87892923503/6-rules-of-thumb-for-mongodb-schema-design-part-2