产品(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端。