ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

MongoDB 聚合管道

2021-11-17 21:31:49  阅读:136  来源: 互联网

标签:聚合 操作符 MongoDB 管道 文档 limit 表达式


为什么需要聚合

一般查询可以通过 find() 方法,但如果是比较复杂的查询或者数据统计的话,find() 方法可能就无能为力,这时需要聚合(aggregate)。

聚合操作处理数据文档并返回计算结果。聚合操作将来自多个文档的值分组在一起,可以对分组的数据执行各种操作以返回单个结果。

MongoDB 提供了三种执行聚合的方法:

  • 聚合管道
  • map- reduce 函数
  • 单一目的聚合方法
什么是聚合管道(aggregation pipeline)

聚合管道可以对数据文档进行变换和组合。聚合管道是基于数据流概念,数据进入管道经过一个或多个 stage,每个 stage 对数据进行操作(筛选,投射,分组,排序,限制或跳过)后输出最终结果。

聚合管道语法

db.collection.aggregate(pipeline, options)
  • pipeline:数组类型

注:聚合管道可以对分片集合进行操作

Pipeline 管道
db.collection.aggregate( [ { <stage> },... ] )

MongoDB 聚合管道由多个 stage 阶段组成。每个 stage 阶段在文档通过管道时转换文档。管道阶段可以在管道中出现多次。

聚合管道原理

db.collection.aggregate([]) 是聚合管道查询使用的方法,参数是数组,每个数组元素就是一个stage,stage 中运用操作符对数据进行处理后再交由下一个stage,直到没有下个stage,就输出最终的结果,而数据的处理则是通过使用管道操作符。

什么是管道操作符

mongoDB 有 4 类操作符用于文档的操作(操作符以 $ 开头)

  • 查询操作符
  • 更新操作符
  • 管道操作符(聚合管道中的操作符)
  • 查询修饰符

在 aggregate 中每个 stage 可以使用的操作符叫做管道操作符

管道操作符分类
  • 阶段操作符(Stage Operators)
  • 表达式操作符(Expression Operators)
  • 累加器(Accumulators)
阶段操作符
db.collection.aggregate( [ { 阶段操作符:表述 }, { 阶段操作符:表述 }, ... ] )
阶段操作符 操作符名称 说明
$count 统计操作符 用于统计文档的数量
$group 分组操作符 用于对文档集合进行分组
$limit 限制操作符 用于限制返回文档的数量
$match 匹配操作符 用于对文档集合进行筛选
$out 输出操作符 将聚合管道的结果文档写入集合。要使用 $out阶段,它必须是管道中的最后一个阶段。
$project 投射操作符 用于重构每一个文档的字段,可以提取字段,重命名字段,甚至可以对原有字段进行操作后新增字段
$skip 跳过操作符 用于跳过指定数量的文档
$sort 排序操作符 用于根据一个或多个字段对文档进行排序
$unwind 拆分操作符 用于将数组中的每一个值拆分为单独的文档
$lookup 连接操作符 用于连接同一个数据库中另一个集合,并获取指定的文档,类似于populate
$addFields 字段操作符 用于给聚合管道的结果文档添加字段

$match 语法

匹配操作符,用于对文档集合进行筛选

{ $match: { <query> } }

$project 语法

用于重构每一个文档的字段,可以提取字段,重命名字段,甚至可以对原有字段进行操作后新增字段

{ $project: { <specification(s)> } } 

specification 的规则如下:

规则 描述
<字段名>: 1 or true 选择需要显示什么字段
_id: 0 or false 不显示 _id (默认显示)
<字段名>: 表达式 使用表达式,可以用于重命名字段,或对其值进行操作,或新增字段
<字段名>: 0 or false 选择需要不返回什么字段,注意:当使用这种用法时,就不要用上面的方法

$addFields 语法

在聚合管道结果添加一些字段信息或者修改字段信息

{ $addField: <document> }

$skip 语法

用于跳过指定数量的文档

{ $skip: <positive integer> }

$limit 语法

用于限制返回文档的数量

{ $limit: <positive integer> }

$count 语法

{ $count: <string> } 
  • string:是输出字段的名称,该字段的值为 count。string 必须是非空字符串,不能以 $ 开头,也不能包含 .点字符

$sort 语法

用于根据一个或多个字段对文档进行排序

{ $sort: { <field1>: <sort order>,<field2>: <sort order> ... } }
  • 1:升序
  • -1:降序

$out 语法

{ $out: "<output-collection>" }

$unwind 语法

用于将数组中的每一个值拆分为单独的文档

{	$unwind:	{		path: <field path>, includeArrayIndex: <string>, 		preserveNullAndEmptyArrays:<boolean>	} }
  • path:字符串类型,数组字段的字段路径,若要指定字段路径,需要在字段名称前加上 $ 符号并将其括在引号内
  • includeArrayIndex:可选项,用于保存元素的数组索引的新字段的名称。名称不能以 $ 符号开头
  • preserveNullAndEmptyArrays:
    • 如果为 true,如果路径为空、没有数组字段或数组为空,则 $unwind 输出文档
    • 如果为 false,如果路径为空、没有数组字段或数组为空,则 $unwind 不输出文档(默认)

$lookup 语法

用于连接同一个数据库中另一个集合,并获取指定的文档

{   $lookup:     {       from: <collection to join>,       localField: <field from the input documents>,       foreignField: <field from the documents of the "from" collection>,       as: <output array field>     }}
字段 描述
from 需要关联的集合名
localField 本集合中需要查找的字段
foreignField 另外一个集合中需要关联的字段
as 输出的字段名

$group 语法

用于对文档集合进行分组

{ $group: { _id: <expression>, <field1>: { <accumulator1> : <expression1> }, ... } }
  • _id:是必须的,用作分组的依据条件

表达式(Expression)

表达式可以包括字段路径和系统变量、文本、表达式对象和表达式操作符。表达式可以嵌套。

{ <field1>: <expression1>, ... }
  • 字段路径表达式:$

  • "$<field>” 等价于 “$$CURRENT.<field>”,其中 CURRENT 是一个系统变量,在大多数阶段默认为当前对象的根.

  • 聚合表达式使用字段路径访问输入文档中的字段。若要指定字段路径,请使用前缀为$符号字段名的字符串,如果字段在嵌入的文档中,则使用点语法。

  • 系统变量表达式:$$系统变量

    • $$CURRENT 表示当前文档

    • $$ROOT 整个文档

  • 字面量表达式:返回不需要解析的值。用于聚合管道可解释为表达式的值

  • 表达式对象

  • 表达式操作符

表达式操作符

表达式操作符主要用于在管道中构建表达式时使用,使用类似于函数那样需要参数,主要用于 $project 操作符中,用于构建表达式,使用方法一般如下:

{ <operator>: [ <argument1>, <argument2> ... ] }# 或{ <operator>: <argument> }
表达式操作符分类
  • 布尔值操作符(Boolean Operators)
  • 集合操作符(Set Operators)
  • 比较操作符(Comparison Operators)
  • 数学操作符(Arithmetic Operators)
  • 字符串操作符(String Operators)
  • 文本搜索操作符(Text Search Operators)
  • 数组操作符(Array Operators)
  • 变量操作符(Variable Operators)
  • 字面量操作符(Literal Operators)
  • 日期操作符(Date Operators)
  • 条件操作符(Conditional Operators)
  • 数据类型操作符(Data Type Operators)
累加器(Accumulators)
累加器操作符 说明
$avg 返回数值的平均值(忽略非数字值)
$max 返回每个组的最高表达式值
$min 返回每个组的最低表达式值
$push 返回每个组的表达式值组成的数组
$sum 返回数值的和(忽略了非数字值)

$avg 语法

{ $avg: [ <expression1>, <expression2>... ] }

$max 语法

{ $max: <expression> }{ $max: [ <expression1>, <expression2>... ] }

$push 语法

{ $push: <expression> }

$sum 语法

{ $sum: <expression> }

聚合管道优化

聚合管道操作有一个优化阶段,该阶段试图重塑管道以提高性能

管道序列优化
  • $project or $addFields) 和 $match 顺序优化

  • $sort 和 $match 顺序优化

  • $skip 和 $limit 顺序优化

  • $project 和 ($skip or $limit) 顺序优化

管道联合优化
  • $sort 和 $limit 联合优化

当 $sort 紧邻 $limit 时,优化器可以将 $limit 合并到 $sort 中。这允许 $sort 操作在进行过程中只维护顶部的 n 个结果,其中 n 是指定的限制,MongoDB 只需要在内存中存储 n 个条目。

  • $limit 和 $limit 联合优化

当一个 $limit 紧接另一个 $limit 之后,这两个阶段可以合并为一个 $limit,其中 $limit 值是两个初始 $limit 值中较小的一个。

  • $skip 和 $skip 联合优化

当一个 $skip 紧接着另一个 $skip 时,这两个阶段可以合并为单个 $skip,其中 $skip 量是两个初始 $skip 量的总和。

  • $match 和 $match 联合优化

当一个 $match 紧跟在另一个 $match 之后时,这两个阶段可以合并为一个结合了条件和 $and 的单个 $match

  • $sort 和 $skip 和 $limit 联合优化

  • $limit 和 $skip 和 $limit 和 $skip 联合优化

标签:聚合,操作符,MongoDB,管道,文档,limit,表达式
来源: https://www.cnblogs.com/ccl971123/p/15569622.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有