mongodb数据处理数据处理(mongodb数据会丢失吗)
mongodb数据库怎么使用
MongoDB是由10gen团队开发的基于分布式存储的开源数据库系统,使用C++编写。MongoDB作为一个文档型数据库,其中数据以键值对的方式来存储。
mongodb数据处理数据处理(mongodb数据会丢失吗)
mongodb数据处理数据处理(mongodb数据会丢失吗)
下面我们来看下MogoDB的基本使用。
1、连接MongoDB数据库
使用如下命令来连接MongoDB数据库
mongo
图1 连接MongoDB数据库
2、查看目前所使用的数据库。
在MongoDB中,想查看使用的是哪个数据库,可以使用如下命令来查看。
db
图2 查看所使用的数据库
3、查看有哪些数据库。
在MongoDB中存在着许多个数据库,对于有哪些数据库,可以使用如下命令来查看。
show db
图3 查看MongoDB中所有的数据库
4、创建数据库。
现阶段所存在的数据库如果不能满足要求,可以使用如下命令来创建新的数据库。
use database_name
其中database_name则代表所要创建的数据库名字,下面将演示创建一个名为offcn的数据库。
use offcn
图4 创建offcn数据库
5、删除数据库
当数据库没有作用时,可以将数据库删除从而释放所占用的空间资源。使用如下命令来进行对数据库进行删除,在删除前应该先选中所要删除的数据库。
use offcn
db.dropDatabase()
图5 删除数据库
MongoDB Aggregation
对数据进行聚合作,然后将计算之后的数据返回。聚合作将多个文档的值组合在依赖,并且可以对分组数据执行各种作返回单个结果。
MongoDB提供三种方式来执行聚合作:aggregation pipeline、map-reduce function、single pure aggregation mods。
MongoDB 聚合作是在数据处理管道的逻辑上建模的。documents可以进入一个用于处理docuemnt然后返回聚合值的多阶段管道。
底层的管道提供了filters(类似于查询的作)和document transformations(修改document的输出形式)作。
其他管道作为document指定具体的属性或者多个属性进行分组和排序,以及用array内容的聚合工具一样。管道的阶段可以使用运算符执行任务。
管道使用MongoDB自带的本地作来执行聚合作更高效,管道是MongoDB执行聚合作的首先。
聚合管道可以作分片collection。聚合管道可以通过使用索引来提高性能。聚合管道内部会进行优化阶段。
可以使用db.collection.aggregate()的explain参数看到执行。
聚合管道来决定需要返回的字段。如果使用只需要的字段,这样可以减少数据量。
addFields + match放入到 addFields之前(如果是 project / $addFields的结果,就不能移动),减少数据量。
match: 先执行$match来减少数据量,然后在执行排序作。
match: 如果在前面添加$match作,可以使用索引来减少数据作。
skip(在3.2开始可以使用):将 project作之前,可以减少数据量。
通常情况下,在重新排序优化之后才会发生阶段合并。
limit:如果不能减少数据量,不会将这两个阶段合并。否则先进行排序,然后获取指定的数量,放入内存。如果在中间含有$skip作,将其放入。
在数据量超过内存限制,这个作需要设置 allowDiskUse=true。
从MongoDB3.6开始,删除了aggregate的选项,将结果作为一条数据的返回。
aggregate可以返回cursor或者数据结果集。在返回的结果中,每个document的大小不能超过16M(这个限制只针对返回的document)。
documents有可能会超过这个限制,db.collection.aggregate()默认返回cursor。
从MongoDB2.6开始,管道阶段的RAM限制为100M。如果超过限制,出错。如果为了处理大量的数据集,使用allowDiskUse选项开启管道阶段的聚合作将数据写入到临时文件。
从MongoDB3.4之后, graphLookup作会忽略这个选项。如果其他阶段有aggregate()作,allowDiskUse=true将会影响这些阶段。
从MongoDB3.2开始,如果按照分片来匹配值,只会在这个分片内进行计算。
聚合作在多个分片上执行作,如果没有指定主分片,这些作会被路由到其他分片上,来减少主分片的负载。
lookup阶段需要在主分片上执行查询。
将聚合管道拆分为两部分,这是为了在分片上执行优化。
作可以 参考实例
MapReduce可以在分片上执行作,分片可以作为输入或者输出。
使用分片作为MapReduce输入源,mongos将作业并行派发到各个分片。mongos会等待所有的作业完成。
如果MapReduce的out字段有分片值,MongoDB使用_id字段作为分片的依据。
作为一个分片输出:
在作的过程中,mapreduce有很多锁:
相关 练习教程
MongoDB是什么,怎么用?看完你就知道了
MongoDB是一款为web应用程序和互联网基础设施设计的数据库管理系统。没错MongoDB就是数据库,是NoSQL类型的数据库。
(1)MongoDB提出的是文档、的概念,使用BSON(类JSON)作为其数据模型结构,其结构是面向对象的而不是二维表,存储一个用户在MongoDB中是这样子的。
使用这样的数据模型,使得MongoDB能在生产环境中提供高读写的能力,吞吐量较于mysql等SQL数据库大大增强。
(2)易伸缩,自动故障转移。易伸缩指的是提供了分片能力,能对数据集进行分片,数据的存储压力分摊给多台。自动故障转移是副本集的概念,MongoDB能检测主是否存活,当失活时能自动提升从为主,达到故障转移。
(3)数据模型因为是面向对象的,所以可以表示丰富的、有层级的数据结构,比如博客系统中能把“评论”直接怼到“文章“的文档中,而不必像myqsl一样创建三张表来描述这样的关系。
(1)文档数据类型
SQL类型的数据库是正规化的,可以通过主键或者外键的约束保证数据的完整性与性,所以SQL类型的数据库常用于对数据完整性较高的系统。MongoDB在这一方面是不如SQL类型的数据库,且MongoDB没有固定的Schema,正因为MongoDB少了一些这样的约束条件,可以让数据的存储数据结构更灵活,存储速度更加快。
(2)即时查询能力
MongoDB保留了关系型数据库即时查询的能力,保留了索引(底层是基于B tree)的能力。这一点汲取了关系型数据库的优点,相比于同类型的NoSQL redis 并没有上述的能力。
(3)能力
MongoDB自身提供了副本集能将数据分布在多台机器上实现冗余,目的是可以提供自动故障转移、扩展读能力。
(4)速度与持久性
MongoDB的驱动实现一个写入语义 fire and forget ,即通过驱动调用写入时,可以立即得到返回得到成功的结果(即使是报错),这样让写入的速度更加快,当然会有一定的不安全性,完全依赖网络。
MongoDB提供了Journaling日志的概念,实际上像mysql的bin-log日志,当需要插入的时候会先往日志里面写入记录,再完成实际的数据作,这样如果出现停电,进程突然中断的情况,可以保障数据不会错误,可以通过修复功能读取Journaling日志进行修复。
(5)数据扩展
MongoDB使用分片技术对数据进行扩展,MongoDB能自动分片、自动转移分片里面的数据块,让每一个里面存储的数据都是一样大小。
MongoDB核心主要是通过mongod程序启动的,而且在启动时不需对MongoDB使用的内存进行配置,因为其设计哲学是内存管理是交给作系统,缺少内存配置是MongoDB的设计亮点,另外,还可通过mongos路由使用分片功能。
MongoDB的主要客户端是可以交互的js shell 通过mongo启动,使用js shell能使用js直接与MongoDB进行交流,像使用sql语句查询mysql数据一样使用js语法查询MongoDB的数据,另外还提供了各种语言的驱动包,方便各种语言的接入。
mongodump和mongorestore,备份和恢复数据库的标准工具。输出BSON格式,迁移数据库。
mongoexport和mongoimport,用来导入导出JSON、CSV和TSV数据,数据需要支持多格式时有用。mongoimport还能用与大数据集的初始导入,但是在导入前顺便还要注意一下,为了能充分利用好mongoDB通常需要对数据模型做一些调整。
mongosniff,网络嗅探工具,用来观察发送到数据库的作。基本就是把网络上传输的BSON转换为易于人们阅读的shell语句。
因此,可以总结得到,MongoDB结合键值存储和关系数据库的特性。因为简单,所以数据极快,而且相对容易伸缩还提供复杂查询机制的数据库。MongoDB需要跑在64位的上面,且单独部署,因为是数据库,所以也需要对其进行热备、冷备处理。
因为本篇文章不是API手册,所有这里对shell的使用也是基础的介绍什么功能可以用什么语句,主要是为了展示使用MongoDB shell的方便性,如果需要知道具体的MongoDB shell语法可以查阅文档。
创建数据库并不是必须的作,数据库与只有在次插入文档时才会被创建,与对数据的动态处理方式是一致的。简化并加速开发过程,而且有利于动态分配命名空间。如果担心数据库或被意外创建,可以开启严格模式。
以上的命令只是简单实例,设如果你之前没有学习过任何数据库语法,同时开始学sql查询语法和MongoDB 查询语法,你会发现哪一个更简单呢?如果你使用的是ja驱动去作MongoDB,你会发现任何的查询都像Hibernate提供出来的查询方式一样,只要构建好一个查询条件对象,便能轻松查询(接下来会给出示例),博主之前熟悉ES6,所以入手MongoDB js shell完成没问题,也正因为这样简洁,完善的查询机制,深深的爱上了MongoDB。
使用ja驱动链接MongoDB是一件非常简单的事情,简单的引用,简单的做增删改查。在使用完ja驱动后我才发现spring 对MongoDB 的封装还不如自身提供出来的东西好用,下面简单的展示一下使用。
这里只举例了简单的链接与简单的MongoDB作,可见其作的容易性。使用驱动时是基于TCP套接字与MongoDB进行通信的,如果查询结果较多,恰好无法全部放进中,将会向发送一个getmore指令获取下一批查询结果。
插入数据到时间,不会等待的响应,驱动会设写入是成功的,实际是使用客户端生成对象id,但是该行为可以通过配置配置,可以通过安全模式开启,安全模式可以校验端插入的错误。
要清楚了解MongoDB的基本数据单元。在关系型数据库中有带列和行的数据表。而MongoDB数据的基本单元是BSON文档,在键值中有指向不定类型值的键,MongoDB拥有即时查询,但不支持联结作,简单的键值存储只能根据单个键来获取值,不支持事务,但支持多种原子更新作。
如读写比是怎样的,需要何种查询,数据是如何更新的,会不会存在什么并发问题,数据结构化的程度是要求高还是低。系统本身的需求决定mysql还是MongoDB。
在关于schema 的设计中要注意一些原则,比如:
数据库是的逻辑与物理分组,MongoDB没有提供创建数据库的语法,只有在插入时,数据库才开始建立。创建数据库后会在磁盘分配一组数据文件,所有、索引和数据库的其他元数据都保存在这些文件中,查阅数据库使用磁盘状态可通过。
是结构上或概念上相似得文档的容器,的名称可以包含数字、字母或 . 符号,但必须以字母或数字开头,完全。
限定名不能超过128个字符,实际上 . 符号在中很有用,能提供某种虚拟命名空间,这是一种组织上的原则,和其他是一视同仁的。在中可以使用。
其次是键值,在MongoDB里面所有的字符串都是UTF-8类型。数字类型包括double、int、long。日期类型都是UTC格式,所以在MongoDB里面看到的时间会比时间慢8小时。整个文档大小会限制在16m以内,因为这样可以防止创建难看的数据类型,且小文档可以提升性能,批量插入文档理想数字范围是10~200,大小不能超过16MB。
(1)索引能显著减少获取文档的所需工作量,具体的对比可以通过 .explain()方法进行对比
(2)解析查询时MongoDB通过选择一个索引进行查询,当没有最适合索引时,会先不同的使用各个索引进行查询,最终选出一个索引做查询
(3)如果有一个a-b的复合索引,那么仅针对a的索引是冗余的
(4)复合索引里的键的顺序是很重要的
(1)单键索引
(2)复合索引
(3)性索引
(4)稀疏索引
如索引的字段会出现null的值,或是大量文档都不包含被索引的键。
如果数据集很大时,构建索引将会花费很长的时间,且会影响程序性能,可通过
当使用 mongorestore 时会重新构建索引。当曾经执行过大规模的删除时,可使用
对索引进行压缩,重建。
(1)查阅慢查询日志
(2)分析慢查询
注意新版本的MongoDB 的explain方法是需要参数的,不然只显示普通的信息。
本节同样主要简单呈现MongoDB副本集搭建的简易性,与副本集的强壮性,容易性
提供主从能力,热备能力,故障转移能力
实际上MongoDB对副本集的作跟mysql主从作是不多的,先看一下mysql的主从数据流动过程
而MongoDB主要依赖的日志文件是oplog
写作先被记录下来,添加到主的oplog里。与此同时,所有从结点oplog。首先,查看自己oplog里一条的时间戳;其次,查询主oplog里所有大于此时间戳的条目;,把那些条目添加到自己的oplog里并应用到自己的库里。从使用长轮询立即应用来自主结点oplog的新条目。
当遇到以下情况,从会停止
local数据库保存了所有副本集元素据和oplog日志
可以使用以下命令查看情况
每个副本集成员每秒钟ping一次其他所有成员,可以通过rs.status()看到上次的心跳检测时间戳和 健康 状况。
这个点没必要过多描述,但是有一个特殊场景,如果从和仲裁都了,只剩下主,他会把自己降级成为从。
如果主的数据还没有写到从库,那么数据不能算提交,当该主变成从时,便会触发回滚,那些没写到从库的数据将会被删除,可以通过rollback子目录中的BSON文件恢复回滚的内容。
(1)使用单链接
只能链接到主,如果链接到从的话,会被拒绝写入作,但是如果没有使用安全模式,因为mongo的fire and forget 特性,会把拒绝写入的异常给吃掉。
(2)使用副本集方式链接
能根据写入的情况自动进行故障转移,但是当副本集进行新的选举时,还是会出现故障,如果不使用安全模式,依旧会出现写不进去,但现实成功的情况。
分片是数据库切分的一个概念实现,这里也是简单总结为什么要使用分片以及分片的原理,作。
当数据量过大,索引和工作数据集占用的内存就会越来越多,所以需要通过分片负载来解决这个问题
(1)分片组件
(2)分片的核心作
分片一个:分片是根据一个属性的范围进行划分的,MongoDB使用所谓的分片键让每个文档在这些范围里找到自己的位置
块:是位于一个分片中的一段连续的分片键范围,可以理解为若干个块组成分片,分片组成MongoDB的全部数据
(3)拆分与迁移
块的拆分:初始化时只有一个块,达到块尺寸64MB或100000个文档就会触发块的拆分。把原来的范围一分为二,这样就有了两个块,每个块都有相同数量的文档。
迁移:当分片中的数据大小不一时会产生迁移的动作,比如分片A的数据比较多,会将分片A里面的一些块转移到分片B里面去。分片集群通过在分片中移动块来实现均衡,是由名为均衡器的软件进程管理的,任务是确保数据在各个分片中保持均匀分布,当集群中拥有块最多的分片与拥有块最少分片的块大于8时,均衡器就会发起一次均衡处理。
启动两个副本集、三个配置、一个mongos进程
配置分片
(1)分片查询类型
(2)索引
分片只允许在_id字段和分片键上添加性索引,其他地方不行,因为这需要在分片间进行通信,实施起来很复杂。
当创建分片时,会根据分片键创建一个索引。
(1)分片键是不可修改的、分片键的选择非常重要
(2)低效的分片键
(3)理想的分片键
(1)部署拓扑
根据不同的数据中心划分
这里写描述
(2)要求
(3)配置的注意事项
需要估计集群大小,可使用以下命令对现有进行分片处理
(4)备份分片集群
备份分片时需要停止均衡器
(1)部署架构
使用64位机器、32位机器会制约mongodb的内存,使其值为1.5GB
(2)cpu
mongodb 只有当索引和工作集都可放入内存时,才会遇到CPU瓶颈,CPU在mongodb使用中的作用是用来检索数据,如果看到CPU使用饱和的情况,可以通过查询慢查询日志,排查是不是查询的问题导致的,如果是可以通过添加索引来解决问题
mongodb写入数据时会使用到CPU,但是mongodb写入时间一次只用到一个核,如果有频繁的写入行为,可以通过分片来解决这个问题
(3)内存
大内存是mongodb的保障,如果工作集大小超过内存,将会导致性能下降,因为这将会增加数据加载入内存的动作
(4)硬盘
mongodb默认每60s会与磁盘强制同步一次,称为后台刷新,会产生I/O作。在重启时mongodb会将磁盘里面的数据加载至内存,高速磁盘将会减少同步的时间
(5)文件系统
使用ext4 和 xfs 文件系统
禁用访问时间
(6)文件描述符
linux 默认文件描述符是1024,需要大额度的提升这个额度
(7)时钟
mongodb各个之间使用ntp
(1)绑定IP
启动时使用 - -bind_ip 命令
(2)身份验证
启动时使用 - -auth 命令
(3)副本集身份认证
使用keyFile,注意keyFile文件的权限必须是600,不然会启动不起来
(1)拓扑结构
搭建副本集至少需要两个,其中仲裁结点不需要有自己的
(2)Journaling日志
写数据时会先写入日志,而此时的数据也不是直接写入硬盘,而是写入内存
但是Journaling日志会消耗内存,所以可以在主库上面关闭,在从库上面启动
可以单独为Journaling日志使用一块固态硬盘
在插入时,可以通过驱动确保Journaling插入后再反馈,但是会非常影响性能。
logpath 选项指定日志存储地址
-vvvvv 选项(v越多,输出越详细)
db.runCommand({logrotare:1}) 开启滚动日志
(1)serverStatus
这里写描述
(2)top
(3)db.currentOp()
动态展示mongodb活动数据
占用当前mongodb端口往上1000号的端口
(1)mongodump
把数据库内容导出成BSON文件,而mongorestore能读取并还原这些文件
(2)mongorestore
把导出的BSON文件还原到数据库
(3)备份原始数据文件
可以这么做,但是,作之前需要进行锁库处理 db.runCommand({fsync:1,lock:true})
db.$cmd.sys.unlock.findOne() 请求解锁作,但是数据库不会立刻解锁,需要使用db.currentOp()验证。
(1)修复
mongd --repair 修复所有数据库
db.runCommand({repairDatabase:1}) 修复单个数据库
修复就是根据Joing文件读取和重写所有数据文件并重建各个索引
(2)压紧
压紧,会重写数据文件,并重建的全部索引,需要停机或者在从库上面运行,如果需要在主库上面运行,需要添加force参数 保证加写锁。
(1)磁盘状态
(2)为提升性能检查索引和查询
总的来说,扫描尽可能少的文档。
保证没有冗余的索引,冗余的索引会占用磁盘空间、消耗更多的内存,在每次写入时还需做更多工作
(3)添加内存
dataSize 数据大小 和 indexSize 索引大小,如果两者的和大于内存,那么将会影响性能。
storageSize超过dataSize 数据大小 两倍以上,就会因磁盘碎片而影响性能,需要压缩。
mongoDB应用篇-mongo聚合查询
如果我们在日常作中,将部分数据存储在了MongoDB中,但是有需求要求我们将存储进去的文档数据,按照一定的条件进行查询过滤,得到想要的结果便于二次利用,那么我们就可以尝试使用MongoDB的聚合框架。
前面我们在学习文档查询的过程中,也介绍过一些查询的作符,其中就有一部分是简单的查询聚合函数,例如 count 、 distinct 、 group 等,如果是简单的数据分析过滤,完全可以使用这些自带的聚合函数以及查询的作符来完成文档的过滤查询作
如果我们遇到了一些数据需要跨多个文本或者统计等作,这个时候可能文档自身也较为复杂,查询作符已经无法满足的时候,这个时候就需要使用MongoDB的聚合查询框架了。
使用聚合框架可以对中的文档进行变换和组合查询,基本上我们使用的时候,都是使用多个构件创建一个管道,用于对一连串的文档进行处理。这里的构件包括 筛选(filter) 、 投射(projecting) 、 分组(grouping) 、 排序(sorting) 、 限制(limiting) 以及 跳过(skipping)
MongoDB中需要使用聚合作,一般使用 aggregate 函数来完成多个聚合之间的连接,aggregate() 方法的基本语法格式如下 :
现在设我们有个articles,里面存储了文章的,大致如下:
但这时我们需要查询出来每一个作者写的文章数量,需要使用aggregate()计算 ,大致如下:
输出的结果为:
通过这个简单的案例我们就能输出想要的数据和属性名,大概分析一下刚刚的聚合查询语句, by_user字段进行分组,代表每个用户一条数据,而num_tutorial则是定义了数值类型计算的结果字段,$sum则是计算总和,相当于每个用户出现一次,都会+1,最终计算出来的总和通过num_tutorial字段进行输出
注:如果管道没有给出预期的结果,就需要进行调试作,调试的时候,可以尝试先给一个管道作符的条件,如果这个时候查询出来的结果是我们想要的,那么我们需要再去指定第二个管道作符,依次作,就会定位到出了问题的作符
前面我们提到聚合查询会使用管道作符,而每一个作符就会接受一连串的文档,对这些文档进行一些类型转换,将转换以后的文档结果传递给下一个管道作符来执行后续的作,如果当前是一个管道作符,那么则会显示给用户的文档数据。不同的管道作符是可以按照顺序组合在一起使用,并且可以被重复执行多次,例如我们可以先使用$match然后再去、 match作。
match管道作符可以使用$gt、$lt、$in等作符,进行过滤,不过需要注意的是不能在$match管道作符中使用空间地理作符。
在实际使用的过程中,尽可能的将 match作符以后,再去投射或者执行分组作的话,是可以利用索引的。
相比较一般的查询作而言,使用管道作,尤其是其中的投射作更加强大。我们可以在查询文档结束以后利用 $project 作符从文档中进行字段的提取,甚至于我们可以重命名字段,将部分字段映射成我们想要展示出去的字段,也可以对一部分字段进行一些有意义的处理。需要注意的是, $project 作符可以传入两个参数,个是需要处理的属性名称,第二个则是0或者1,如果传入1,则代表当前的属性是需要显示出来的,如果是0或者不写,默认都是代表这个字段不需要显示出来
当然第二个参数也可以是一个表达式或者查询条件,满足当前表达式的数据也可以进行显示,接下来我们先准备一点数据:
接下来,我们来查询,条件是字段为abc,quantity要大于5,并且我们只要和pr字段的结果,其他都排除掉:
可以看到结果为:
如果我们想要在原基础上改变某个字段的名称,例如将改为_code,可以利用$来完成,如下:
可以看到我们指定的名称_code,而这个别名对应的字段使用$作为前缀标记,代表将字段映射为_code,可以看到结果:
我们在投影的时候,除了可以将某个字段映射成其他字段以外,还可以针对某个字段进行一些简单的运算,最常见的就是 四则运算 ,即
加法( subtract )、乘法( divide )、求模( $mod ) ,
除此之外,还支持对字段进行 关系运算 (大小比较( " eq" )、大于( " gte" )、小于( " lte" )、不等于( " ifNull" ) )、
逻辑运算 (与( " or" )、非 ( " concat" )、截取( " toLower" ) )等
我们基于上面的需求,设每一个价格是按照元为单位,现在要求输出W为单位,那么我们就需要对pr进行除法运算,如下:
除此之外,我们也可以将计算完毕的pr改名为prW,即:
可以看到输出的结果为:
这时有一个需求,要求我们返回数据的同时还要yyyy-MM-dd格式的时间字符串,这个时候我们就需要对date字段进行时间函数和字符串混合处理了,如下:
这里需要注意的一点是, year:" substr函数将date字段的结果截取成字符串即可实现拼接
group的_id上,代表按照当前字段进行分组,例如,我们这据进行分组:
在我们针对某个字段进行分组以后,我们可以针对每个分组进行一些作符的使用,常见的例如: $sum 、 $g 、 $min 、 $max 、 $first 、 $last 。
$g 作符用来返回每一个分组内的平均值
现在我们基于前面的分组,我们想要算出来每个组内的平均价格是多少,如下:
$min 和 $max 作符用于返回分组内的值和最小的值
除了平均值以外,我们现在将的和的价格也要列出来,这个时候就可以使用这两个作符了,如下:
$first 、 $last 则是可以获取当前分组中个或者一个的某个字段的结果,如下:
除此之外,我们还可以在分组的时候使用数组作符,例如 $addToSet 可以判断,当前数组如果不包含某个条件,就添加到当前数组中, $push 则不管元素是否存在,都直接添加到数组中
注意:大部分管道作符都是流式处理的,只要有新的文档进入,就可以对新的文档进行处理,但是 $group 代表必须收到全部文档以后才可以进行分组作,才会将结果传递给后续的管道作符,这就意味着,如果当前mongo是存在分片的,会先在每个分片上执行完毕以后,再把结果传递mongos进行统一的分组,剩下的管道作符也不会在每个分片,而是mongos上执行了
如果我们现在遇到一些文档比较复杂,比如存在内嵌文档的存在,某个属性里面嵌套了一个数组,但是我们需要对内嵌的数组文档进行分析过滤等查询处理,这个时候就可以使用 $unwind 作符将每一个文档中的嵌套数组文件拆分为一个个的文档便于进行后续的处理,例如我们需要将之前的set中关于请求的以及ip的信息拆分出来,原始的格式如下:
我们可以使用命令进行拆分,如下:
结果为:
可以看到数据则是按照每一条信息的方式展示出来了,方便后续的计算以及输出,但是需要注意的一点是,这种方式,如果该文档中没有拆分的字段,或者是空数组,默认会直接排除,如果我们需要空数组等也输出计算出来,则可以指定 preserveNullAndEmptyArrays 参数,设置为true,则代表空数组或者不存在的文档也要拆分输出出来,即:
我们可以在管道查询的过程中,按照某个属性值或者多个属性的结果进行顺序排序,排序的方式与普通查询作符中的sort作符表现一致,与其他管道作符一样,可以在任何阶段使用,但是,需要注意的一点是,建议在管道作符阶段进行排序,因为此时的排序是可以触发索引的,如果在后续阶段进行排序,会消耗大量内存,并且耗时会很久,尤其是在有 $group 的情况下,如果放在 $group 作符后面,会发现等到的时间很久,不仅仅是无法触发索引的问题,还和 $group 作符是等待所有数据完毕才会触发的特性有关,因此需要格外注意。
结果如下,按照我们想要的结果进行了排序:
limit,只返回前两条数据,如下:
结果如下:
除了 skip,与之前的查询作符作用也是一样的,用于在已经查询完毕的结果集中跳过前N条数据以后进行返回,我们将$skip加在刚刚的查询后面,如下:
这个时候可以看到返回的结果为空,什么结果都没有了,这是因为前一步管道已经限制了仅仅返回2条,而接着我们又跳过了前两条文档,因此返回的结果为空,我们将顺序调换一下,看看:
可以看到结果如下,与刚才的结果无异:
管道查询作符有很多,除了上面学习的常用的部分,还有几十个,需要了解全部的可以参考:
除此之外,我们在学习的过程中了解到,部分查询作符是可以触发索引的,例如 $project 、 $group 或者 $unwind 作符,因此我们也建议 如果可以的话,尽量先使用这类管道作符进行数据过滤,可以有效减少数据集大小和数量,而且管道如果不是直接从原先的中使用数据,那就无
法在筛选和排序中使用索引 ,例如我们先进行管道作,再去将过滤好的数据进行 $sort 排序,会导致无法使用索引,效率大幅度下降,因此如果我们需要涉及到 $sort 作的时候,如果可以尽可能在最开始就处理,这个时候可以使用索引,效率较高,然后再去进行管道查询筛选与分组等其他作,可以有效的提高查询的效率。另外需要注意的一点是,在 MongoDB中会对每一个管道查询做限制,例如某一步管道查询作导致内存占用超过20%,这个时候就会报错,无法继续使用管道 ,因为mongoDB本身每次是16Mb的数据量,为了尽可能避免或者减少这种问题,建议可以考虑尽可能的使用 $match 作符过滤无用数据,减少数据总大小。同时也 因为管道查询是多步执行,例如 $group 则是等待所有数据完毕才会执行,因此可能会导致整体执行时间较久 ,也因为这样,才不建议在较高的实时查询需求上使用管道和查询,而是在 设计的时候尽可能直接使用查询作符进行数据查询,触发更多的索引,更快的销量查询出来想要的结果。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系 836084111@qq.com 删除。