【Mongodb】视图 && 索引
准备工作
准备2个集合的数据,后面视图和索引都会用到
1个订单集合,一个收款信息集合
var orders = new Array();
var shipping = new Array();
var addresses = ["广西省玉林市", "湖南省岳阳市", "湖北省荆州市", "甘肃省兰州市", "吉林省松原市", "江西省景德镇", "辽宁省沈阳市", "福建省厦门市", "广东省广州市", "北京市朝阳区"]; for (var i = 10000; i < 20000; i++) {
var orderNo = i + Math.random().toString().substr(2, 5);
orders[i] = { orderNo: orderNo, userId: i, price: Math.round(Math.random() * 10000) / 100, qty: Math.floor(Math.random() * 10) + 1, orderTime: new Date(new Date().setSeconds(Math.floor(Math.random() * 10000))) }; var address = addresses[Math.floor(Math.random() * 10)];
shipping[i] = { orderNo: orderNo, address: address, recipienter: "Wilson", province: address.substr(0, 3), city: address.substr(3, 3) }
}
db.order.insert(orders);
db.shipping.insert(shipping);
视图
概述
A MongoDB view is a queryable object whose contents are defined by an aggregation pipeline on other collections or views. MongoDB does not persist the view contents to disk. A view’s content is computed on-demand when a client queries the view. MongoDB can require clients to have permission to query the view. MongoDB does not support write operations against views.
Mongodb的视图基本上和SQL的视图一样
- 数据源(集合或视图)
- 提供查询
- 不实际存储硬盘
- 客户端发起请求查询时计算而得
1. 创建视图
有两种方法创建视图
db.createCollection(
"<viewName>",
{
"viewOn" : "<source>",
"pipeline" : [<pipeline>],
"collation" : { <collation> }
}
)
db.createView(
"<viewName>",
"<source>",
[<pipeline>],
{
"collation" : { <collation> }
}
)
一般使用db.createView
viewName : 必须,视图名称
source : 必须,数据源,集合/视图
[<pipeline>] : 可选,一组管道,可见管道是Mongodb比较重要的一环
1.1 单个集合创建视图
假设现在查看当天最高的10笔订单视图,例如后台某个地方需要实时显示金额最高的订单
db.createView(
"orderInfo", //视图名称
"order", //数据源
[
//筛选符合条件的订单,大于当天,这里要注意时区
{ $match: { "orderTime": { $gte: ISODate("2020-04-13T16:00:00.000Z") } } },
//按金额倒序
{ $sort: { "price": - } },
//限制10个文档
{ $limit: },
//选择要显示的字段
//0: 排除字段,若字段上使用(_id除外),就不能有其他包含字段
//1: 包含字段
{ $project: { _id: , orderNo: , price: , orderTime: } }
]
)
然后就可以直接使用orderInfo这个视图查询数据
db.orderInfo.find({})
返回结果
{ "orderNo" : "", "price" : , "orderTime" : ISODate("2020-04-14T13:49:42.220Z") }
{ "orderNo" : "", "price" : 99.99, "orderTime" : ISODate("2020-04-14T15:08:07.240Z") }
{ "orderNo" : "", "price" : 99.99, "orderTime" : ISODate("2020-04-14T15:15:41.158Z") }
{ "orderNo" : "", "price" : 99.98, "orderTime" : ISODate("2020-04-14T13:41:07.199Z") }
{ "orderNo" : "", "price" : 99.98, "orderTime" : ISODate("2020-04-14T13:31:58.150Z") }
{ "orderNo" : "", "price" : 99.98, "orderTime" : ISODate("2020-04-14T15:15:35.162Z") }
{ "orderNo" : "", "price" : 99.94, "orderTime" : ISODate("2020-04-14T14:13:02.160Z") }
{ "orderNo" : "", "price" : 99.93, "orderTime" : ISODate("2020-04-14T15:17:25.210Z") }
{ "orderNo" : "", "price" : 99.92, "orderTime" : ISODate("2020-04-14T13:09:41.196Z") }
{ "orderNo" : "", "price" : 99.92, "orderTime" : ISODate("2020-04-14T15:16:15.187Z") }
1.2 多个集合创建视图
其实跟单个是集合是一样,只是多了$lookup连接操作符,视图根据管道最终结果显示,所以可以关联多个集合(若出现这种情况就要考虑集合设计是否合理,mongodb本来就是文档型数据库)
db.orderDetail.drop()
db.createView(
"orderDetail",
"order",
[
{ $lookup: { from: "shipping", localField: "orderNo", foreignField: "orderNo", as: "shipping" } },
{ $project: { "orderNo": , "price": , "shipping.address": } }
]
)
查询视图,得到如下结果
{ "_id" : ObjectId("5e95af8c4ef6faf974b4a6c3"), "orderNo" : "", "price" : 85.94, "shipping" : [ { "address" : "北京市朝阳区" } ] }
{ "_id" : ObjectId("5e95af8c4ef6faf974b4a6c4"), "orderNo" : "", "price" : 29.04, "shipping" : [ { "address" : "吉林省松原市" } ] }
{ "_id" : ObjectId("5e95af8c4ef6faf974b4a6c5"), "orderNo" : "", "price" : 90.69, "shipping" : [ { "address" : "湖南省岳阳市" } ] }
{ "_id" : ObjectId("5e95af8c4ef6faf974b4a6c6"), "orderNo" : "", "price" : 75.05, "shipping" : [ { "address" : "辽宁省沈阳市" } ] }
{ "_id" : ObjectId("5e95af8c4ef6faf974b4a6c7"), "orderNo" : "", "price" : 76.84, "shipping" : [ { "address" : "江西省景德镇" } ] }
{ "_id" : ObjectId("5e95af8c4ef6faf974b4a6c8"), "orderNo" : "", "price" : 60.25, "shipping" : [ { "address" : "江西省景德镇" } ] }
{ "_id" : ObjectId("5e95af8c4ef6faf974b4a6c9"), "orderNo" : "", "price" : 19.14, "shipping" : [ { "address" : "广东省广州市" } ] }
{ "_id" : ObjectId("5e95af8c4ef6faf974b4a6ca"), "orderNo" : "", "price" : 31.5, "shipping" : [ { "address" : "北京市朝阳区" } ] }
{ "_id" : ObjectId("5e95af8c4ef6faf974b4a6cb"), "orderNo" : "", "price" : 76.16, "shipping" : [ { "address" : "吉林省松原市" } ] }
{ "_id" : ObjectId("5e95af8c4ef6faf974b4a6cc"), "orderNo" : "", "price" : 93.98, "shipping" : [ { "address" : "辽宁省沈阳市" } ] }
可以看到,mongodb不是像SQL那样把连接的表当成列列出,而是把连接结果放在数组里面,这很符合Mongodb文档型结构。
2. 修改视图
假设现在需要增加一个数量的字段
db.runCommand({
collMod: "orderInfo",
viewOn: "order",
pipeline: [
{ $match: { "orderTime": { $gte: ISODate("2020-04-13T16:00:00.000Z") } } },
{ $sort: { "price": - } },
{ $limit: },
//增加qty
{ $project: { _id: , orderNo: , price: , qty: , orderTime: } }
]
})
当然,也可以删除视图,重新用db.createView()创建视图
3. 删除视图
db.orderInfo.drop();
索引
概述
Indexes support the efficient execution of queries in MongoDB. Without indexes, MongoDB must perform a collection scan, i.e. scan every document in a collection, to select those documents that match the query statement. If an appropriate index exists for a query, MongoDB can use the index to limit the number of documents it must inspect.
索引能提供高效的查询,没有索引的查询,mongole执行集合扫描,相当于SQL SERVER的全表扫描,扫描每一个文档。
数据存在存储介质上,大多数情况是为了查询,查询的快慢直接影响用户体验,mongodb索引也是空间换时间,添加索引,CUD操作都会导致索引重新生成,影响速度。
1. 准备工作
1.1 准备200W条数据
var orderNo = * ;
for (var i = ; i < ; i++) {
//分批次插入,每次20000条
var orders = new Array();
for (var j = ; j < ; j++) {
var orderNo = orderNo++;
orders[j] = { orderNo: orderNo, userId: i + j, price: Math.round(Math.random() * ) / , qty: Math.floor(Math.random() * ) + , orderTime: new Date(new Date().setSeconds(Math.floor(Math.random() * ))) };
}
//不需写入确认
db.order.insert(orders, { writeConcern: { w: } });
}
1.2 mongodb的查询计划
db.collection.explain().<method(...)>
一般使用执行统计模式,例如
db.order.explain("executionStats").find({orderNo:})
返回的executionStats对象字段说明
部分字段说明
字段 | 说明 |
---|---|
executionSuccess | 是否执行成功 |
nReturned | 返回匹配文档数量 |
executionTimeMillis | 执行时间,单位:毫秒 |
totalKeysExamined | 索引检索数目 |
totalDocsExamined | 文档检索数目 |
查看未加索引前查询计划
db.order.explain("executionStats").find({orderNo:})
截取部分返回结果,可以看出
- executionTimeMillis : 用时1437毫秒
- totalDocsExamined : 扫描文档200W
- executionStages.stage : 集合扫描
"executionStats" : {
"executionSuccess" : true,
"nReturned" : ,
"executionTimeMillis" : ,
"totalKeysExamined" : ,
"totalDocsExamined" : ,
"executionStages" : {
"stage" : "COLLSCAN",
1.3 查看当前集合统计信息
db.order.stats()
截取部分信息,可以看出现在存储文件大小大概为72M
{
"ns" : "mongo.order",
"size" : ,
"count" : ,
"avgObjSize" : ,
"storageSize" : ,
2. 创建索引
db.order.createIndex({ orderNo: }, { name: "ix_orderNo" })
索引名称不是必须,若不指定,按 字段名称_排序类型组合自动生成,索引名称一旦创建不能修改,若要修改,只能删除索引重新生成索引,建议还是建索引的时候就把索引名称设置好。
2.1 执行查询计划
db.order.explain("executionStats").find({orderNo:})
截取部分结果,直观就可以感觉查询速度有了质的提升,再看查询计划更加惊讶
- nReturned : 匹配到1个文档
- executionTimeMillis : 0,呃。。
- totalKeysExamined : 总共检索了1个索引
- totalDocsExamined : 总共检索了1个文档
- executionStages.stage : FETCH,根据索引去检索指定文档,像SQL的Index Seek
"executionStats" : {
"executionSuccess" : true,
"nReturned" : ,
"executionTimeMillis" : ,
"totalKeysExamined" : ,
"totalDocsExamined" : ,
"executionStages" : {
"stage" : "FETCH"
这里只介绍最简单的单个字段索引,mongodb还有很多索引
- 复合索引(Compound Indexes):对多个字段做索引
- 多键索引(Multikey Indexes): 一个字段多个值做索引,通常是数组
- 全文索引(Text Indexes): 对文本检索,可以对字段设置不同权重
- 通配符索引(Wildcard Indexes):可以将对象的所有/指定的值做索引
- 更多
转发请标明出处:https://www.cnblogs.com/WilsonPan/p/12704474.html
【Mongodb】视图 && 索引的更多相关文章
- 84. 从视图索引说Notes数据库(下)
作用和代价上文介绍了关系型数据库里的索引.Notes数据库里的索引隐藏在视图概念里(本文的讨论仅仅针对Notes的视图索引,不包括全文索引.).开发者创建的视图仅仅是存放在数据库里的一条设计文档.数据 ...
- MongoDB的索引(三)
MongoDB的索引: 1. _id索引 该索引是大多数集合默认创建的索引,也就是说用户每插入一个数据,MongoDB会自动生成一条唯一的_id字段. 2. 单键索引 单键索引是最普通的索引,它不会自 ...
- MongoDB 覆盖索引查询
MongoDB 覆盖索引查询 官方的MongoDB的文档中说明,覆盖查询是以下的查询: 所有的查询字段是索引的一部分 所有的查询返回字段在同一个索引中 由于所有出现在查询中的字段是索引的一部分, Mo ...
- 83. 从视图索引说Notes数据库(上)
索引是数据库系统重要的feature,不管是传统的关系型数据库还是时兴的NoSQL数据库,它攸关查询性能,因而在设计数据库时须要细加考量.然而,Lotus Notes隐藏技术底层.以用户界面为导向.追 ...
- MongoDB数据库索引
前面的话 索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录.这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查 ...
- MongoDB数据库索引构建情况分析
前面的话 本文将详细介绍MongoDB数据库索引构建情况分析 概述 创建索引可以加快索引相关的查询,但是会增加磁盘空间的消耗,降低写入性能.这时,就需要评判当前索引的构建情况是否合理.有4种方法可以使 ...
- MongoDB索引(一) --- 入门篇:学习使用MongoDB数据库索引
这个系列文章会分为两篇来写: 第一篇:入门篇,学习使用MongoDB数据库索引 第二篇:进阶篇,研究数据库索引原理--B/B+树的基本原理 1. 准备工作 在学习使用MongoDB数据库索引之前,有一 ...
- 第五章 MySQL事务,视图,索引,备份和恢复
第五章 MySQL事务,视图,索引,备份和恢复 一.事务 1.什么是事务 事务是一种机制,一个操作序列,它包含了一组数据库操作命令,并且把所有的命令作为一个整体一起向系统提交或撤销操作请求.要么都执行 ...
- MongoDb进阶实践之七 MongoDB的索引入门
一.引言 好久没有写东西了,MongoDB系列的文章也丢下好长时间了.今天终于有时间了,就写了一篇有关索引的文章.一说到"索引",用过关系型数据库的人都应该知道它是一个什么 ...
- 给MongoDB添加索引
用过数据库的都知道,数据库索引与书籍的索引类似,都是用来帮助快速查找的. MongoDB的索引跟关系型数据库的索引几乎一致. 1. 索引的创建 mongodb采用ensureInd ...
随机推荐
- 【Weiss】【第03章】练习3.22、3.23、3.24:无代码题,栈的思考题
[练习3.22] a.提出支持栈的Push和Pop操作以及第三种操作FindMin的数据结构,其中FindMin 返回该数据结构的最小元素,所有操作在最坏情况下的运行时间都是O(1). b.证明,如果 ...
- 基于《仙剑奇侠传柔情版》利用Java的简单实现(一)
基于<仙剑奇侠传柔情版>利用Java的简单实现(一) 2018-12-01 23:55:36 by Louis 一,新建一个类GameFrame.class,具体代码如下: pack ...
- 【简说Python WEB】flask-mail电子邮件异步Asynchronous
系统环境:Ubuntu 18.04.1 LTS Python使用的是虚拟环境:virutalenv Python的版本:Python 3.6.9 flask-mail电子邮件异步Asynchronou ...
- SpringBoot2整合Redis多数据源
配置文件属性 spring: redis: database: 1 host: 192.168.50.144 port: 6379 password: timeout: 600 #Springboot ...
- Swift 4.0 数组(Array)之过滤器(filter)的使用
我们先来定义一个常量整型数组 let array = [5, 4, 3, 1, 2] 过滤器(filter)使用之筛选出大于3的值 let resultArray = array.filter { ( ...
- Spring bean配置 入门
Spring 的入门案例:(IOC) IOC 的底层实现原理(结构图2.01) 图:2.01 IOC:Inversion of Control 控制反转,指的是对象的创建权反转(交给)给Spring ...
- JavaScript 模式》读书笔记(4)— 函数1
从这篇开始,我们会用很长的章节来讨论函数,这个JavaScript中最重要,也是最基本的技能.本章中,我们会区分函数表达式与函数声明,并且还会学习到局部作用域和变量声明提升的工作原理.以及大量对API ...
- 题解 P1985 【[USACO07OPEN]翻转棋】
讲讲我的做法 刚开始做这道题的时候,看到\(n<=15\),我这个\(6\)年级的蒟蒻的第1反应是状压\(dp\).貌似不好做.然而,等到我在省中集训的时候,老师的一席话,让我豁然开朗.今天我准 ...
- MQ的理论理解
MQ(消息队列)简介 概念 : 消息队列(MQ)是一种应用程序对应用程序的通信方法. 应用程序通过写和检索出入列队的针对应用程序的数据(消息)来通信,而无需专用连接来链接它们. 消息传递指的是程序之间 ...
- 01FPGA设计流程
今天学习了FPGA设计流程的视频,我理解要做一个完整的FPGA系统,所要经历的步骤,先将它简单总结如下: 我在对上面的流程图进行解释: 第一:设计定义就是我们这个FPGA系统或者FPGA设计所要实现的 ...