设为首页 收藏本站
查看: 926|回复: 0

[经验分享] MongoDB 一对多关系建模

[复制链接]

尚未签到

发表于 2017-12-15 17:20:13 | 显示全部楼层 |阅读模式
  本篇博客翻译自:
  http://blog.mongodb.org/post/87200945828/6-rules-of-thumb-for-mongodb-schema-design-part-1?mkt_tok=3RkMMJWWfF9wsRonsq7Ldu%2FhmjTEU5z14uUsUKGxhokz2EFye%2BLIHETpodcMTcVnM7zYDBceEJhqyQJxPr3FLdcN0tJuRhTrCw%3D%3D
  

  备注:本译文不是严格意义上的翻译,仅仅是在基于对该原文的理解之上,尽可能表达清楚。如有疑问或不妥,请參考原文。
  

  非常多刚从传统SQL开发转向MongoDB开发的朋友都会问到一个问题:怎样用MongoDB表达传统关系数据库中的一对多(1 to n)关系?
  基于MongoDB丰富的表达力,我们不能说我们必须採用一个标准的方法来进行1 to n的建模。
  稍后我们从3个详细场景来展开解说。
  

  首先。我们将1 to n中的n进行场景细化。这个n到底代表多大的量级呢?是几个到几十个?还是几个到几千个?还是成千上万个?
  1) 1 to n(n代表好几个。或几十个,反正不太多)
  比方每一个Person会有多个Address。此种情况下,我们採用最简单的嵌入式文档来建模。
  

{  name: 'Kate Monster', >  addresses : [     { street: '123 Sesame St', city: 'Anytown', cc: 'USA' },     { street: '123 Avenue Q', city: 'New York', cc: 'USA' }  ]}  
这样的建模的方式包括了显而易见的长处和缺点:

  长处:你不须要运行单独的查询就能够获得某个Person的全部Address信息。
  缺点:你无法像操作独立文档那样来操作Address信息。
  你必须首先操作(比方查询)Person文档后,才有可能继续操作Address。
  在本实例中,我们不须要对Address进行独立的操作。且Address信息仅仅有在关联到某一个详细Person后才有意义。所以结论是:採用这样的embedded(嵌入式)建模是很适合Person-Address场景的。
  

  2)1 to n(n代表好些个,比方几十个。甚至几百个)
  比方产品(Product)和零部件(part),每一个产品会有非常多个零部件。这样的场景下,我们能够採用引用方式来建模,例如以下:
  

零部件(Part):{    _id : ObjectID('AAAA'),    partno : '123-aff-456',    name : '#4 grommet',    qty: 94,    cost: 0.94,    price: 3.99}  

产品(Product):{    name : 'left-handed smoke shifter',    manufacturer : 'Acme Corp',    catalog_number: 1234,    parts : [     // array of references to Part documents        ObjectID('AAAA'),    // reference to the #4 grommet above        ObjectID('F17C'),    // reference to a different Part        ObjectID('D2AA'),        // etc    ]}  首先每一个part作为单独的文档存在。每一个产品中包括一个数组类型字段(parts),这个数组中存放的是全部该产品包括的零部件的编号(_id主键)。当你须要依据某一个产品编号查询该产品包括的全部部件信息时。你能够运行下面操作:
  

> product = db.products.findOne({catalog_number: 1234});   // Fetch all the Parts that are linked to this Product> product_parts = db.parts.find({_id: { $in : product.parts } } ).toArray() ;  
这样的建模方式的优缺点也很明显:

  长处:部件是作为独立文档(document)存在的,你能够对某一部件进行独立的操作。比方查询或更新。
  缺点:如上,你必须通过两次查询才干找到某一个产品所属的全部部件信息。
  在本例中。这个缺点是能够接受的。本身实现起来也不难。并且,通过这样的建模,你能够轻易的将1 to n扩展到n to n。即一个产品能够包括多个部件,同一时候一个部件也能够被多个产品所引用(即同一部件能够被多个产品使用)。
  

  3)1 to n(这个n代表非常大的数值,比方成千上万。甚至更大)
  比方。每个主机(host)会产生非常大数量的日志信息(logmsg)。
  在这样的情况下,假设你採用嵌入式建模,则一个host文档会非常庞大,从而轻易超过MongoDB的文档限制大小。所以不可行。假设你採用第二中方式建模,用数组来存放全部logmsg的_id值,这样的方式相同不可行。由于当日志非常多时,即使单单引用objectId也会轻易超过文档限制大小。所以此时,我们採用下面方式:
  

主机(hosts):{    _id : ObjectID('AAAB'),    name : 'goofy.example.com',    ipaddr : '127.66.66.66'} 日志(logmsg):{    time : ISODate("2014-03-28T09:42:41.382Z"),    message : 'cpu is on fire!',    host: ObjectID('AAAB')       // Reference to the Host document}  
我们在logsmg中,存放对host的_id引用就可以。
  

  综上所述,在对1 to n关系建模时,我们须要考虑:
  1)n代表的数量级非常小。且n代表的实体不须要单独操作时,能够採用嵌入式建模。
  2)n代表的数量级比較大。或者n代表的实体须要单独进行操作时,採用在1中用Array存放引用的方式建模。
  3)n代表的数量级很大时,我们没有选择。仅仅能在n端加入一个引用到1端。
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-424433-1-1.html 上篇帖子: python使用mongodb 下篇帖子: MongoDB 的 Nodejs 驱动基础
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表