MongoDB与关系型数据库的建模还是有许多不同,因为MongoDB支持内嵌对象和数组类型。MongoDB建模有两种方式,一种是内嵌(Embed),另一种是连接(Link)。那么何时Embed何时Link呢?那得看两个实体之间的关系是什么类型。

一对一的关系:Embed,比如用户信息集合有Address字段,Address字段有省、市、县三个字段。建模如下:

一对多关系:一篇文章有多条评论,为1对多关系

由于MongoDB对单个文档(document)有大小限制16M(高于v1.8),设计时也要将这个限制纳入考虑中。

多对多关系:学生和课程是多对多的关系,一个学生可以选多门课程,一门课程有多名学生参与。

多对多使用了连接(Linking),连接是通过引用(References)来连接两个集合。MongoDB References有两种:一种是 手动引用(Manual References),另一种是DBRefs。

Manual References:

(user集合)

(post集合)

红框地方就是Manual References,如果想查询一篇文章的作者信息,首先在post集合找出那篇文章,然后在user集合查找出用户的全部信息。但是假如有这么一个场景:用户可以对图片,文章等各种资源评论,所有的评论都放在comment集合中,如果只是使用Manual References,就分不清楚评论到底是属于哪类资源了,图片?文章?。所以有了DBRef。

DBRef的形式:

{ $ref : <value>, $id : <value>, $db : <value> }
$ref:集合名称;$id:引用的id;$db:数据库名称,可选参数。
可以看到DBRef的结构比Manual References的复杂,占用的空间大,但是功能也强大,如果要跨数据库连接,上面讲的评论集合的例子,都得需要使用DBRef,MongoDB提供了函数来解析DBRef,不用像Manual References需要自己手动写两次查询。
 
关于MongoDB的数据建模MongoDB官网也给出了一些建议。这些建议都是提供了一些参考,实际建模需要根据具体的需求来分析,
分析数据经常会执行哪些操作(排序,查找,修改)来选择Embed和Link。 ---------

  我们来看mongodb另一个非常有意思的东西,那就是$lookup,我们知道mongodb是一个文档型的数据库,而且它也是最像关系型数据库的

一种nosql,但是呢,既然mongodb是无模式的,自然就很难在关系型数据库中非常擅长的多表关联上发挥作用,在这之前,我们可以使用DbRef,但

是呢,在mongodb 3.2 中给你增加了一个相当牛逼的手段,那就是$lookup,而且放到了aggreation这种重量级的pipeline分析框架上,自然就是一等

公民了,牛逼哈~。

$lookup:

db.product.insert({"_id":1,"productname":"商品1","price":15})
db.product.insert({"_id":2,"productname":"商品2","price":36}) db.orders.insert({"_id":1,"pid":1,"ordername":"订单1"})
db.orders.insert({"_id":2,"pid":2,"ordername":"订单2"})
db.orders.insert({"_id":3,"pid":2,"ordername":"订单3"})
db.orders.insert({"_id":4,"pid":1,"ordername":"订单4"}) db.product.find()
db.orders.find()

语法:
db.product.aggregate([
{
$lookup:
{
from: "orders",
localField: "_id",
foreignField: "pid",
as: "inventory_docs"
}
}
])
然后展示的结果如下:
 1 /* 1 */
2 {
3 "_id" : 1.0,
4 "productname" : "商品1",
5 "price" : 15.0,
6 "inventory_docs" : [
7 {
8 "_id" : 1.0,
9 "pid" : 1.0,
10 "ordername" : "订单1"
11 },
12 {
13 "_id" : 4.0,
14 "pid" : 1.0,
15 "ordername" : "订单4"
16 }
17 ]
18 }
19
20 /* 2 */
21 {
22 "_id" : 2.0,
23 "productname" : "商品2",
24 "price" : 36.0,
25 "inventory_docs" : [
26 {
27 "_id" : 2.0,
28 "pid" : 2.0,
29 "ordername" : "订单2"
30 },
31 {
32 "_id" : 3.0,
33 "pid" : 2.0,
34 "ordername" : "订单3"
35 }
36 ]
37 }

下面我简单介绍一些$lookup中的参数:

from:需要关联的表【orders】

localField: 【product】表需要关联的键。

foreignField:【orders】的matching key。

as:           对应的外键集合的数据,【因为可能是一对多的,对吧】

参考文档:http://www.cnblogs.com/huangxincheng/p/5728791.html

      http://blog.csdn.net/bugall/article/details/45062663

												

mongodb 多表关联处理 : 内嵌以及连接(手动引用、DBref) 、aggregate中$lookup的更多相关文章

  1. html的<a>标签,表单,内嵌框架

      一.  <a>标签 0. 用图片当链接,就是把图片当成链接文字即可 <a href="http://www.baidu.com/" title="跳 ...

  2. form表单以及内嵌框架标签

    今关于今天所学习的东西又复杂又简单,上午学习了form表单,也是挺简单的:搭配table表格使用也是非常熟练. 下午讲了讲给网页内嵌框架标签以及在内嵌框架标签中添加其他的网页:还有在内嵌框架标签中添加 ...

  3. mongodb对数组元素及内嵌文档进行增删改查操作(转)

    from:https://my.oschina.net/132722/blog/168274 比如我有一个user类,他包含一个标签属性,这个标签是一个数组,数组里面的元素是内嵌文档,格式如下: &l ...

  4. MongoDB .Net Driver(C#驱动) - 内嵌数组/嵌入文档的操作(增加、删除、修改、查询(Linq 分页))

    目录 一.前言 1. 运行环境 二.前期准备工作 1. 创建 MongoDBContext MongoDb操作上下文类 2.创建测试类 3.创建测试代码 三.内嵌数组增加元素操作 1.Update.S ...

  5. MongoDB对数组元素及内嵌文档进行增删改查操作

    比如我有一个user类,他包含一个标签属性,这个标签是一个数组,数组里面的元素是内嵌文档,格式如下: {    "_id" : "195861",    &qu ...

  6. 学习MongoDB 五: MongoDB查询(数组、内嵌文档)(二)

    一.简介 我们上一篇介绍了db.collection.find()可以实现根据条件查询和指定使用投影运算符返回的字段省略此参数返回匹配文档中的所有字段,我们今天介绍了对数组和内嵌文档的查询操作,尤其是 ...

  7. mongodb数据文件结构——record是内嵌BSON的双向链表,多个record或索引组成extent

    数据文件结构 Extent 在每一个数据文件内,MongoDB把所存储的BSON文档的数据和B树索引组织到逻辑容器“Extent”里面.如下图所示(my-db.1和my-db.2 是数据库的两个数据文 ...

  8. 修改注册表打开PDF内嵌的zip等文件

    今天在打开一个 PDF 文件的时候,发现文件里面嵌入的 .zip 文件无法打开.当然 .png 之类的文件还是可以打开的.网上的各种“信任管理器”白名单方法都是无效的.后来查了官网说明,得知是因为这类 ...

  9. 【cl】多表查询(内、外连接)

    交叉连接(cross join):该连接产生的结果集笛卡尔积 a有7行,b有8行    a的第一行与b的每一行进行连接,就有8条a得第一行 7*8=56条 select a.real_name,s.u ...

随机推荐

  1. iOS10以上App请求用户授权系统设置权限

    <key>NSAppleMusicUsageDescription</key> <string>使用媒体资源</string> <key>N ...

  2. 让Flash内心崩溃的HTML5历史

    对于HTML5,在今天这个互联网时代,大部分人应该至少都听说过这个名字,或许很多人对HTML5的了解都起于一句话:FLASH杀手. HTML5其实早已不是什么新鲜的事物了,其最初的雏形早在2004年就 ...

  3. Java 迭代器删除元素ConcurrentModificationException异常。

    Java是不支持容器类在使用迭代器迭代过程中,使用如 list.remove(obj)方法删除元素.否则会抛出ava.util.ConcurrentModificationException异常.应该 ...

  4. 查看window系统有哪些服务

    右键点击开始菜单按钮,选择“运行”(也可以快捷键 WIN+R 打开) 在运行框中输入命令services.msc打开服务窗口 在服务窗口列出了系统的所有服务,有运行的,也有停止的,可以点击“状态”列对 ...

  5. Python_004(列表和元组)

    一.列表 1. 列表: 列表的创建:li = [],列表中可以放置字符串,元组,列表,字典,列表等各种数据类型,32位的Python可以存放2^32个数据 2. 列表的索引和切片 列表的索引:格式ls ...

  6. PHP Trait特性

    php类的单继承性,无法同时从两个基类中继承属性和方法,为了解决这个问题,使用Trait特性解决. Trait是一种代码复用技术,为PHP的单继承限制提供了一套灵活的代码复用机制. 用法:通过在类中使 ...

  7. 轮询,WebSocket和P2P--记一次QQ交谈IM

    问题:

  8. 《图解设计模式》读书笔记5-1 composite模式

    目录 代码 角色 想法 Composite模式即组合模式.它能够使容器和内容具有一致性,创造出递归结构. 举个例子:在文件系统中,文件夹既是内容,也是容器,具有一致性,这样一来,文件系统形成递归结构. ...

  9. 判断文件是否存在的shell脚本代码!

    实现代码一 #shell判断文件夹是否存在 #如果文件夹不存在,创建文件夹 if [ ! -d "/Top" ]; then mkdir -p /Topfi #shell判断文件, ...

  10. [LeetCode] 72. Edit Distance(最短编辑距离)

    传送门 Description Given two words word1 and word2, find the minimum number of steps required to conver ...