mongodb 关系、引用、覆盖索引查询
一、关系
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 关系、引用、覆盖索引查询的更多相关文章
- MongoDB 覆盖索引查询
MongoDB 覆盖索引查询 官方的MongoDB的文档中说明,覆盖查询是以下的查询: 所有的查询字段是索引的一部分 所有的查询返回字段在同一个索引中 由于所有出现在查询中的字段是索引的一部分, Mo ...
- MongoDB覆盖索引查询
官方的MongoDB的文档中说明,覆盖查询是以下的查询: 1. 所有的查询字段是索引的一部分 2. 所有的查询返回字段在同一个索引中 由于所有出现在查询中的字段是索引的一部分, MongoDB 无需在 ...
- mysql优化-覆盖索引查询,join
1 原始sql: SELECT a.* FROM event_data a WHERE a.receive_time >= '2018-03-28 00:00:00' AND a.receive ...
- SQL Server查询性能优化——覆盖索引(二)
在SQL Server 查询性能优化——覆盖索引(一)中讲了覆盖索引的一些理论. 本文将具体讲一下使用不同索引对查询性能的影响. 下面通过实例,来查看不同的索引结构,如聚集索引.非聚集索引.组合索引等 ...
- MYSQL的全表扫描,主键索引(聚集索引、第一索引),非主键索引(非聚集索引、第二索引),覆盖索引四种不同查询的分析
文章出处:http://inter12.iteye.com/blog/1430144 MYSQL的全表扫描,主键索引(聚集索引.第一索引),非主键索引(非聚集索引.第二索引),覆盖索引四种不同查询的分 ...
- SQL Server 查询性能优化——覆盖索引
覆盖索引又可以称为索引覆盖. 解释一: 就是select的数据列只用从索引中就能够取得,不必从数据表中读取,换句话说查询列要被所使用的索引覆盖. 解释二: 索引是高效找到行的一个方法,当能通过检索索引 ...
- 在MySQL中如何使用覆盖索引优化limit分页查询
背景 今年3月份时候,线上发生一次大事故.公司主要后端服务器发生宕机,所有接口超时.宕机半小时后,又自动恢复正常.但是过了2小时,又再次发生宕机. 通过接口日志,发现MySQL数据库无法响应服务器.在 ...
- mysql高效索引之覆盖索引
概念 如果索引包含所有满足查询需要的数据的索引成为覆盖索引(Covering Index),也就是平时所说的不需要回表操作 判断标准 使用explain,可以通过输出的extra列来判断,对于一个索引 ...
- mysql索引之六:mysql高效索引之覆盖索引
概念 如果索引包含所有满足查询需要的数据的索引成为覆盖索引(Covering Index),也就是平时所说的不需要回表操作 判断标准 使用explain,可以通过输出的extra列来判断,对于一个索引 ...
随机推荐
- CSS伪类选择器
一.CSS伪类选择器用于给某些选择器添加效果语法规则:选择器:伪选择器例:a:link {color: #FF0000} 未访问的链接 a:visited {color: #00FF00} 已访问的链 ...
- EXCEL设置选中单元格样式
你想这样啊,试试这段代码看行不:右键工作表名称--查看代码,在空白处粘贴就可以 Private Sub Worksheet_SelectionChange(ByVal Target As Range) ...
- struts2 validation.xml 注意点
1.首先应该注意validation.xml的名字,一定要以Action的类名加“-validation.xml”作为文件名.入LoginAction-validation.xml. 2.LoginA ...
- 查看上下文切换的多的进程(find which process take the most context switch)
这是原文链接http://serverfault.com/questions/190049/find-out-which-task-is-generating-a-lot-of-context-swi ...
- Bootstrap 导航栏和登陆框
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- Linux内核--网络栈实现分析(四)--网络层之IP协议(上)
本文分析基于Linux Kernel 1.2.13 原创作品,转载请标明http://blog.csdn.net/yming0221/article/details/7514017 更多请看专栏,地址 ...
- springMVC参数传递
web.xml文件 <?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi=& ...
- Linux(centeros)下安装jdk
首先需要说明的是有的Linux系统自带jdk,这个jdk是openjdk,可以通过java-version查看 所以安装的步骤是,首先删除系统自带的(如果有)openjdk 1. rpm -qa | ...
- Grpc微服务从零入门
快速入门 安装 JDK 毫无疑问,要想玩Java,就必须得先装Java JDK,目前公司主要使用的是Oracle JDK 8,安装完成后要配置环境才能正常使用,真蠢,不过也就那么一下下,认了吧.配置方 ...
- kali 在线教学群 第一次 公开课 小结(1)
kali 在线教学群 第一次 公开课 小结(1) 文/玄魂 1.1 需要准备的基础环境 vmware 虚拟机,kali 2.0 镜像,科学上网工具包.这三项内容,可以在本人的微信订阅号“xuanhun ...