MongoDB之聚合操作

MongoDB之聚合操作

文章目录

  • MongoDB之聚合操作
    • 一、聚合简介
    • 二、aggregation pipeline分析
      • 2.1 聚合操作语法格式
      • 2.2 聚合指令的字段解释:
      • 2.3 管道操作符可选指令分析
      • 2.4 read(write) Concern 和 read(write)Preference
    • 三、 参考文档

一、聚合简介

  • MongoDB中的聚合操作将多个文档中的值组合在一起,并可对分组数据执行各种操作,以返回单个结果。 在SQL中的 count(*)与group by组合相当于mongodb 中的聚合功能。
  • MongoDB为我们提供了三种方法来实现聚合操作。分别是aggregation pipeline,Map-Reduce和Single Purpose Aggregation Operations。

个人理解:聚合操作中主要使用到了“管道”的概念。管道的入口是一个集合(及该集合内的所有文档),管道的出口是你所需要的数据。这个管道中间是有一个个功能节点组成的,可以类比实际生活中一节一节的管道,每个功能节点都会对上一个节点的结果进行一定的操作,如过滤掉某些文档、对文档进行排序等等。相当于把对某个集合的一系列操作使用一个指令完成,比一个指令一个指令操作的优势在于Mongo会在上一个操作结束之后将结果保留在内存中直接进行下一个操作,会更加节省资源速度会更快

二、aggregation pipeline分析

Mongo版本:4.0

2.1 聚合操作语法格式

db.collection.aggregate
	{
	  aggregate: "" || 1,
	  pipeline: [ , <...> ],
	  explain: ,
	  allowDiskUse: ,
	  cursor: ,
	  maxTimeMS: ,
	  bypassDocumentValidation: ,
	  readConcern: ,
	  collation: ,
	  hint: ,
	  comment: ,
	  writeConcern: 
	}

2.2 聚合指令的字段解释:

字段名 类型 解释 是否为必填字段
aggregate string 要聚合的目标集合名(使用1表明指令不可知) 必填
pipeline array 管道操作符。所有需要对集合进行的操作都写在这里 必填
explain boolean 选择是否返回指定aggregate各个阶段管道的执行计划信息,对于multi-document transactions不可用 可选
allowDiskUse boolean 选择是否允许Mongo使用磁盘缓存。每个阶段管道限制为100MB的内存,设置为true时,如果大于100MB的数据可以先将数据写入对应数据目录的子目录中 的唯一并以_tmp结尾的文档中 可选
cursor document 指定一个文档使其包含一个游标对象。使用{}去创建一个默认批大小的游标,如需要指定批大小可以使用{ batchSize: }. 可选
maxTimeMS non-negative integer 以ms为单位指定对于游标操作的时间限制。当该字段为空时视为0值,即默认的无时间限制。Mongo会以与db.killOp()指令相同的机制去中止超时操作 可选
bypassDocumentValidation boolean 仅当你在管道操作符中使用$out时才可以使用。表明是否允许Mongo忽略文档的验证要求 可选
readConcern document 指定读策略,详见下文 可选
collation document 该字段允许MongoDB的用户根据不同的语言定制排序规则 可选
hint string or document 用于指定Mongo使用用户提供的索引项 可选
comment string 可选
writeConcern document 指定写策略,详见下文 可选

2.3 管道操作符可选指令分析

进列举部分常用字段,Mongo DB版本为4.0

字段名 解释
$match 过滤操作,筛选符合条件文档,作为下一阶段的输入 $match的语法和查询表达式db.collection.find() 的语法相同 注意:1. 不能在$match操作符中使用$where 表达式操作符。 2. $match尽量出现在管道的前面,这样可以提早过滤文档,加快聚合速度。 3. 如果$match出现在最前面的话,可以使用索引来加快查询。
$limit 限制经过管道的文档数量, $limit的参数只能是一个正整数
$skip 从待操作集合开始的位置跳过文档的数目 $skip参数也只能为一个正整数
$group 可以将文档依据指定字段的不同值进行分组,如果选定了需要进行分组的字段,就可以将指定的字段传递给$group函数的_id字段 注意:1.$group的输出是无序的。 2.$group操作默认实在内存中进行的,超过此限制会报错,若要允许处理大型数据集,allowDiskUse 将选项设置为启用 $group 操作真实写入临时文件
$sort 对文档按照指定字段排序,1表示正序,-1表示倒序。注意:1.如果将$sort放到管道前面的话可以利用索引,提高效率 2.在管道中如果$sort出现在$limit之前的话,$sort只会对前$limit个文档进行操作,这样在内存中也只会保留前$limit个文档,从而可以极大的节省内存 3.$sort操作符默认在内存中进行,,超过此限制会报错,若要允许处理大型数据集,allowDiskUse 将选项设置为启用 $group 操作真实写入临时文件。
$project 通过重命名,添加或删除字段重塑文档。你也可以重新计算值,并添加子文档。例如,下面的例子包括title并排除name:{$project:{title:1,name:0}};以下是把name重命名为title的例子:{$project{title:"$name"}};下面是添加一个新的total字段,并用price和tax字段计算它的值的例子:{$project{total:{$add:["$price","$tax"]}}}
$unwind 将数组分解为单个的元素,并与文档的其余部分一同返回 注意:1.如果$unwind目标字段不存在,则整个文档都会被忽略过滤掉 2.如果$unwind目标字段不是一个数组,则会报错 3.如果$unwind目标字段数组为空,则该文档也会被忽略过滤掉
$out 用户将聚合的结果输出到指定的集合,如果要使用$out则必须在整个管道操作的最后阶段 如果指定的集合尚不存在,$out 操作会在当前数据库中创建一个新的集合。集合不是可见的直到聚合完成。如果聚合失败,MongoDB 不会创建集合。 如果集合指定的 $out 操作已经存在,然后完成后的聚合,$out 阶段以原子方式以新的结果集合替换现有集合的,$out 操作不会更改任何存在于以前的集合的索引。如果聚合失败$out 则不会对现有集合做任何更改。
$redact 字段所处的document结构的级别. $redact还有三个重要的参数: 1)$$DESCEND: 返回包含当前document级别的所有字段,并且会继续判字段包含内嵌文档,内嵌文档的字段也会去判断是否符合条件。 2)$$PRUNE:返回不包含当前文档或者内嵌文档级别的所有字段,不会继续检测此级别的其他字段,即使这些字段的内嵌文档持有相同的访问级别。 3)$$KEEP:返回包含当前文档或内嵌文档级别的所有字段,不再继续检测此级别的其他字段,即使这些字段的内嵌文档中持有不同的访问级别。
comment string

2.4 read(write) Concern 和 read(write)Preference

  • readPreference 主要控制客户端 Driver 从复制集的哪个节点读取数据,这个特性可方便的实现读写分离、就近读取等策略.
    – primary 只从 primary 节点读数据,这个是默认设置
    – primaryPreferred 优先从 primary 读取,primary 不可服务,从 secondary 读
    – secondary 只从 scondary 节点读数据
    – secondaryPreferred 优先从 secondary 读取,没有 secondary 成员时,从 primary 读取
    – nearest 根据网络距离就近读取
  • readConcern 决定到某个读取数据时,能读到什么样的数据
    – local 能读取任意数据,这个是默认设置
    – majority 只能读取到"成功写入到大多数节点的数据"
  • readPreference 和 readConcern 可以配合使用
  • readConcern 的初衷在于解决“脏读”的问题,比如用户从 MongoDB 的 primary 上读取了某一条数据,但这条数据并没有同步到大多数节点,然后 primary 就故障了,重新恢复后 这个primary 节点会将未同步到大多数节点的数据回滚掉,导致用户读到了“脏数据”。当指定 readConcern 级别为 majority 时,能保证用户读到的数据“已经写入到大多数节点”,而这样的数据肯定不会发生回滚,避免了脏读的问题。需要注意的是,readConcern 能保证读到的数据“不会发生回滚”,但并不能保证读到的数据是最新的,这个官网上也有说明:“Regardless of the read concern level, the most recent data on a node may not reflect the most recent version of the data in the system.”
  • 有用户误以为,readConcern 指定为 majority 时,客户端会从大多数的节点读取数据,然后返回最新的数据。
    实际上并不是这样,无论何种级别的 readConcern,客户端都只会从“某一个确定的节点”(具体是哪个节点由 readPreference 决定)读取数据,该节点根据自己看到的同步状态视图,只会返回已经同步到大多数节点的数据。

三、 参考文档

  • Mongo DB官方文档 https://docs.mongodb.com/manual/reference/command/aggregate/index.html
  • 学习MongoDB 十一: MongoDB聚合(Aggregation Pipeline基础篇上)(三)https://blog.csdn.net/congcong68/article/details/51619882
  • MongoDB学习笔记——聚合操作之聚合管道(Aggregation Pipeline)https://www.cnblogs.com/AlvinLee/p/6085442.html

你可能感兴趣的:(Mongo,DB)