MongoDB关联关系解析以及java操作关联关系
来源:互联网 发布:mac mini 电源线 编辑:程序博客网 时间:2024/05/20 22:40
传统关系型数据库中,关系关系通过一个外键来表述很清楚。那么在MongoDB中如何表达传统关系数据库中的一对多(1 to n )关系或者多对多( n to n )呢?
基于MongoDB丰富的表达力,我们不能说必须采用向关系数据库那样有一个标准的方法来进行1 to n的关系表达。我们将从3个具体场景来表达MongoDB的关联关系。
首先,我们将1 to n中的n进行场景细化。这个n究竟代表多大的量级呢?是几个到几十个?还是几个到几千个?还是成千上万个?
1 to n(n代表好几个,或几十个,反正不太多)
比如每个Person会有多个Address。此种情况下,我们采用最简单的嵌入式文档来建模。
{ name: 'wx', addresses : [ { street: '123 Sesame St', city: 'Anytown', cc: 'USA' }, { street: '123 Avenue Q', city: 'New York', cc: 'USA' } ]}
需执行如下语句:
db.persion.insert({name:"wx",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场景的。
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 ]}
执行的核心语句:
db.Product.insert({xxxx,"parts":[]});db.Product.update({name:"left-handed smoke shifter"},{$pushAll:{parts:["ObjectId('575cf4cdb9140c7ed2a3b877')","ObjectId('575cf4d0b9140c7ed2a3b878')"]}});
首先每个part作为单独的文档存在。每个产品中包含一个数组类型字段(parts),这个数组中存放的是所有该产品包含的零部件的编号(_id主键)。当你需要根据某一个产品编号查询该产品包含的所有部件信息时,你可以执行以下操作:
product = db.Product.findOne({name:"left-handed smoke shifter"});xxxdb.Part.find({_id:{$in:product.parts}}).toArray();[ { "_id" : ObjectId("575cf4cdb9140c7ed2a3b877"), "partno" : "part1" xxx }, { "_id" : ObjectId("575cf4d0b9140c7ed2a3b878"), "partno" : "part2" xxxx }]
这种建模方式的优缺点也非常明显:
优点:部件是作为独立文档(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}
执行的关键语句为:
db.hosts.insert({name:"comput1",ipAddr:"192.168.199.199"});db.logmsg.insert({_id:ObjectId("575d057cb9140c7ed2a3b87a"),message:"cpu is on fire"})db.logmsg.update({message:"cpu is on fire"},{host:ObjectId("575d057cb9140c7ed2a3b87a")})
我们在logsmg中,存放对host的_id引用即可。
综上所述,在对1 to n关系建模时,我们需要考虑:
1)n代表的数量级很小,且n代表的实体不需要单独操作时,可以采用嵌入式建模。
2)n代表的数量级比较大,或者n代表的实体需要单独进行操作时,采用在1中用Array存放引用的方式建模。
3)n代表的数量级非常大时,我们没有选择,只能在n端添加一个引用到1端。
Java操作关系
- MongoDB关联关系解析以及java操作关联关系
- 关联关系
- 关联关系
- 关联关系
- 关联关系
- 关联关系
- 利用关联关系操作对象
- 关联关系的级联操作
- 关联关系的级联操作
- 关联关系的级联操作
- 依赖关系 、关联关系
- hibernate的关联关系 以及生成策略
- 泛化、聚合、关联关系以及场景图用例图
- [code]关联关系-双向关联
- 12-hibernate关联关系的级联操作
- hibernate_级联操作、关联关系映射
- 关联关系和依赖关系
- 【UML】关系之关联关系
- memcached源码阅读----使用libevent和多线程模型
- 7天学会Maven(第二天——Maven 标准目录结构)
- 【EF】 更新条目时出错。有关详细信息,请参见内部异常。
- centos6.5下LNMP环境中修改配置文件后nginx重启失败的解决方法
- Map.Entry 遍历之泛型
- MongoDB关联关系解析以及java操作关联关系
- mysql 5.6安装成功后如何设置密码?
- 上机笔试题1及程序源码
- 简单的jdbc操作数据库例子,高效率插入数据
- Android中的Shape使用总结
- 多线程——NSThread
- 7天学会Maven(第一天——了解 Maven)
- Roman to Integer
- #90 – 单步调试VS2010自带的源码(Stepping Into .NET Source Code in Visual Studio 2010)