一、关系

  MongoDB 的关系表示多个文档之间在逻辑上的相互联系。文档间可以通过嵌入和引用来建立联系。MongoDB 中的关系可以是:1对1,1对多,多对1,多对多。

一个用户可以用多个地址,这是典型的一对多关系。

  user文档可以是:

{
"_id":ObjectId("52ffc33cd85242f436000001"),
"name": "Tom Hanks",
"contact": "987654321",
"dob": "01-01-1991"
}

  address文档可以是:

{
"_id":ObjectId("52ffc4a5d85242602e000000"),
"building": "22 A, Indiana Apt",
"pincode": 123456,
"city": "Los Angeles",
"state": "California"
}

  1、嵌入式关系

  使用嵌入式方法,可以把地址文档嵌入到用户的文档中

{
"_id":ObjectId("52ffc33cd85242f436000001"),
"contact": "987654321",
"dob": "01-01-1991",
"name": "Tom Benzamin",
"address": [
{
"building": "22 A, Indiana Apt",
"pincode": 123456,
"city": "Los Angeles",
"state": "California"
},
{
"building": "170 A, Acropolis Apt",
"pincode": 456789,
"city": "Chicago",
"state": "Illinois"
}]
}

  如果这样保存的话可以这样获取用户的地址:

db.users.findOne({"name":"Tom Benzamin"},{"address":1})

  这种数据结构的缺点是,如果用户和用户地址在不断增加,数据量不断变大,会影响读写性能。

  2、引用式方法

  这种方法类似于关系型数据库中的外键,将address的_id存到user文档中

  

{
"_id":ObjectId("52ffc33cd85242f436000001"),
"contact": "987654321",
"dob": "01-01-1991",
"name": "Tom Benzamin",
"address_ids": [
ObjectId("52ffc4a5d85242602e000000"),
ObjectId("52ffc4a5d85242602e000001")
]
}

  我们可以读取这些用户地址的对象id(ObjectId)来获取用户的详细地址信息。这种方法需要两次查询,第一次查询用户地址的对象id(ObjectId),第二次通过查询的id获取用户的详细地址信息。

  

var result = db.users.findOne({"name":"Tom Benzamin"},{"address_ids":1})
var addresses = db.address.find({"_id":{"$in":result["address_ids"]}})

二、数据库引用

  mongodb的引用有两种:手动引用(Manual References)与 DBRefs

  如果我们在不同的集合中 (address_home, address_office, address_mailing, 等)存储不同的地址(住址,办公室地址,邮件地址等)。这时候我们在调用不同地址时,也需要指定集合,一个文档从多个集合引用文档,我们应该使用 DBRefs。

  DBRef的形式:

{ $ref : , $id : , $db :  }

  其中$ref:集合名称,$id:引用的id,$db:数据库名称(可选)。

  以下实例中用户数据文档使用了 DBRef, 字段 address:

{
"_id":ObjectId("53402597d852426020000002"),
"address": {
"$ref": "address_home",
"$id": ObjectId("534009e4d852427820000002"),
"$db": "w3cschoolcc"},
"contact": "987654321",
"dob": "01-01-1991",
"name": "Tom Benzamin"
}

  address DBRef 字段指定了引用的地址文档是在 address_home 集合下的 w3cschoolcc 数据库,id 为 534009e4d852427820000002。

  以下代码中,我们通过指定 $ref 参数(address_home 集合)来查找集合中指定id的用户地址信息:

var user = db.users.findOne({"name":"Tom Benzamin"})
var dbRef = user.address
db[dbRef.$ref].findOne({"_id":(dbRef.$id)})

  以上实例返回了 address_home 集合中的地址数据:

{
"_id" : ObjectId("534009e4d852427820000002"),
"building" : "22 A, Indiana Apt",
"pincode" : 123456,
"city" : "Los Angeles",
"state" : "California"
}

三、覆盖索引查询

  覆盖查询是以下的查询:

  • 所有的查询字段是索引的一部分
  • 所有的查询返回字段在同一个索引中

  

  由于所有出现在查询中的字段是索引的一部分, MongoDB 无需在整个数据文档中检索匹配查询条件和返回使用相同索引的查询结果。因为索引存在于RAM中,从索引中获取数据比通过扫描文档读取数据要快得多。

  例:user集合:

{
"_id": ObjectId("53402597d852426020000002"),
"contact": "987654321",
"dob": "01-01-1991",
"gender": "M",
"name": "Tom Benzamin",
"user_name": "tombenzamin"
}

  创建联合索引,字段为gender和user_name

db.users.ensureIndex({gender:1,user_name:1})

  现在,该索引会覆盖以下查询:

db.users.find({gender:"M"},{user_name:1,_id:0})

  对于上述查询,MongoDB的不会去数据库文件中查找。相反,它会从索引中提取数据,这是非常快速的数据查询。由于我们的索引中不包括 _id 字段,_id在查询中会默认返回,我们可以在MongoDB的查询结果集中排除它。下面的实例没有排除_id,查询就不会被覆盖:

db.users.find({gender:"M"},{user_name:1})

  如果所有索引字段是一个数组则不能使用覆盖索引查询,所有索引字段是一个子文档。

mongodb 关系、引用、覆盖索引查询的更多相关文章

  1. MongoDB 覆盖索引查询

    MongoDB 覆盖索引查询 官方的MongoDB的文档中说明,覆盖查询是以下的查询: 所有的查询字段是索引的一部分 所有的查询返回字段在同一个索引中 由于所有出现在查询中的字段是索引的一部分, Mo ...

  2. MongoDB覆盖索引查询

    官方的MongoDB的文档中说明,覆盖查询是以下的查询: 1. 所有的查询字段是索引的一部分 2. 所有的查询返回字段在同一个索引中 由于所有出现在查询中的字段是索引的一部分, MongoDB 无需在 ...

  3. mysql优化-覆盖索引查询,join

    1 原始sql: SELECT a.* FROM event_data a WHERE a.receive_time >= '2018-03-28 00:00:00' AND a.receive ...

  4. SQL Server查询性能优化——覆盖索引(二)

    在SQL Server 查询性能优化——覆盖索引(一)中讲了覆盖索引的一些理论. 本文将具体讲一下使用不同索引对查询性能的影响. 下面通过实例,来查看不同的索引结构,如聚集索引.非聚集索引.组合索引等 ...

  5. MYSQL的全表扫描,主键索引(聚集索引、第一索引),非主键索引(非聚集索引、第二索引),覆盖索引四种不同查询的分析

    文章出处:http://inter12.iteye.com/blog/1430144 MYSQL的全表扫描,主键索引(聚集索引.第一索引),非主键索引(非聚集索引.第二索引),覆盖索引四种不同查询的分 ...

  6. SQL Server 查询性能优化——覆盖索引

    覆盖索引又可以称为索引覆盖. 解释一: 就是select的数据列只用从索引中就能够取得,不必从数据表中读取,换句话说查询列要被所使用的索引覆盖. 解释二: 索引是高效找到行的一个方法,当能通过检索索引 ...

  7. 在MySQL中如何使用覆盖索引优化limit分页查询

    背景 今年3月份时候,线上发生一次大事故.公司主要后端服务器发生宕机,所有接口超时.宕机半小时后,又自动恢复正常.但是过了2小时,又再次发生宕机. 通过接口日志,发现MySQL数据库无法响应服务器.在 ...

  8. mysql高效索引之覆盖索引

    概念 如果索引包含所有满足查询需要的数据的索引成为覆盖索引(Covering Index),也就是平时所说的不需要回表操作 判断标准 使用explain,可以通过输出的extra列来判断,对于一个索引 ...

  9. mysql索引之六:mysql高效索引之覆盖索引

    概念 如果索引包含所有满足查询需要的数据的索引成为覆盖索引(Covering Index),也就是平时所说的不需要回表操作 判断标准 使用explain,可以通过输出的extra列来判断,对于一个索引 ...

随机推荐

  1. 修改Eclipse的 workspace目录

    1.进入 Window > Preferences > General > Startup and Shutdown 选中 Prompt for workspace on start ...

  2. 使用github与jekyll搭建个人博客(一)

    虽然使用博客园还没有多久,但是最近看到一些大神的博客觉得很是炫酷.于是突发奇想,想要搭建自己的博客站点儿.编程菜鸟一枚,还是想要记录下最近的搭建博客经历. 使用github搭建个人博客的方式有很多,百 ...

  3. ajax 跨域请求时url参数添加callback=?会实现跨域问题

    例如: 1.在 jQuery 中,可以通过使用JSONP 形式的回调函数来加载其他网域的JSON数据,如 "myurl?callback=?".jQuery 将自动替换 ? 为正确 ...

  4. 【整理】--C++变量概述

    1.变量概述及特殊变量初始化 a.引用 b.常量 c.静态 d.静态常量(整型) e.静态常量(非整型) 初始化:常量和引用,必须通过参数列表进行初始化. 静态成员变量的初始化也颇有点特别,是在类外初 ...

  5. 字符串匹配的Boyer-Moore算法

    作者: 阮一峰    http://www.ruanyifeng.com/blog/2013/05/boyer-moore_string_search_algorithm.html 上一篇文章,我介绍 ...

  6. 循环处理--sqlserver

    alter PROCEDURE [dbo].[sp_gongzi] @gongzi_yf varchar(7) as DECLARE  @input_id varchar(20)DECLARE  @s ...

  7. go程序注册为windows服务

    cmd下运行:nssm install 服务名 go打包好的exe文件 nssm下载地址:http://nssm.cc/,将下载好nssm.exe放到/windows/system32文件夹下

  8. [ASE][Daily Scrum]11.27

    View Shilin Liu 设计死亡处理 Yiming Liao 处理tank-子弹碰撞事件     Server Songtao He 修复子弹队列满时的bug Junbei Zhang 服务器 ...

  9. IIS负载均衡ARR路由请求到ARR服务器和处理服务器

    .net web 使用IIS ARR(Application Request Route)技术实现web的高性能.高可靠.易扩展及负载均衡.ARR的使用请参考 IIS负载均衡-Application ...

  10. asp.net identity 2.2.0 在MVC下的角色启用和基本使用(一)

    基本环境:asp.net 4.5.2 第一步:在App_Start文件夹中的IdentityConfig.cs中添加角色控制器. 在namespace xxx内(即最后一个“}”前面)添加 角色控制类 ...