笔记
Posted YuYunTan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了笔记相关的知识,希望对你有一定的参考价值。
MongoDB实战第二版笔记(7)第六章笔记
1、MongoDB的聚合框架等价于SQL的GROUP BY语句,其允许定义一系列文档操作,然后在单个调用里作为数组发送给MongoDB。
2、为调用聚合框架,需要定义管道。聚合管道里的每一步输出都作为下一步输入,每一步都在输入文档执行单个操作并生成输出文档。
3、聚合管道操作包含下面的部分:
命令 | 作用 |
---|---|
$project | 指定输出文档里的字段(项目化) |
$match | 选择要处理的文档,与find()类似 |
$limit | 限制传递给下一步的文档数量 |
$skip | 跳过一定数量的文档 |
$unwind | 扩展数组,为每个数组入口生成一个输出文档 |
$group | 根据key来分组文档,主要用于聚合管道,可以处理多个文档的聚合数据,提供诸如min、max、average的统计功能。 |
$sort | 排序文档 |
$geoNear | 选择某个地理附近的文档 |
$out | 把管道的结果写入某个集合 |
$redact | 控制特定数据的访问 |
该代码定义聚合框架管道,包含一个匹配、组合排序:
db.products.aggregate([$match:...,$group:...,$sort:...])
该代码定义的管道,其中:
- 商品集合传递给
$match
,只从输入集合里选择一部分文档。 -
$match
的输出结果传递给$group
操作符,然后通过key排序,提供新的信息,比如求综合和求平均值。 $group
输出结果传递给$sort
操作符,然后将排序结果返回给最终结果。
4、SQL对比聚合框架
SQL命令 | 集合框架操作符 |
---|---|
SELECT | $project $group functions :$sum ,$min ,$avg ,etc |
FROM | db.collectionNames.aggregate(…) |
JOIN | $unwind |
WHERE | $match |
GROUP | BY $group |
HAVING | $match |
5、使用$out
操作符,会自动把聚合管道的输出结果保存到集合里。如果集合不存在,则$out
操作符会创建一个集合,或者如果存在,就会完全取代现有的集合。此外创建新的集合失败的话,MongoDB不会修改之前的集合。
示例是把聚合管道的集合保存到一个命名的集合里:
mainCategorySummary:
db.products.aggregate([
$group:_id:'$main_cat_id',
count:$sum:1,
$out:'mainCategorySummary'
,
])
6、$project
操作符允许我们过滤可以传递给管道下一个阶段的字段。$match
允许通过限制文档数量传递下一步的数据量,但 $project
可以用来限制每个传给下一步文档的大小。限制每个文档的大小可以改善性能,尤其是在处理大文档并且只需要每个文档一部分数据的时候。
7、$unwind
允许扩展数组,对每个输入文档的数组生成一个输出文档,可以提供另外一种类型的MongoDB连接,这样就能使用每个子文档来连接文档。
8、$group
输出文档的其他字段限制使用 $group
函数
$group 函数 | 作用 |
---|---|
$addToSet | 为组里唯一的值创建一个数组 |
$first | 组里的第一个值,只有前缀$$$sort才有意义 |
$last | 组里最后一个值,只有前缀$$$sort才有意义 |
$max | 组里某个字段的最大值 |
$min | 组里某个字段的最小值 |
$avg | 某个字段的平均值 |
$push | 返回组内所有值的数组,不去除重复值 |
$sum | 求组内所有值的和 |
9、$addToSet
和 $push
区别,集合中的元素必须确保唯一,某个给定的值不能在集合里出现两次,而且可以通过 $addToSet
强制实行,而 $push
操作符没有这个限制,集合中的值可以不唯一。因此相同元素可以在 $push
创建的数组里多次出现。
10、物化视图提供一种高效和易用的方式来提前生成的数据结果,通过提前生成这些信息,可以节约大量的生成需要数据的时间,也便于应用程序预处理信息。$$$out操作的失败安全性是生成等价物理视图的关键。
11、MongoDB的聚合管道包含许多可用来重塑文档的函数,可以生成一个包含最初文档没有的字段的新文档,通过会与 $project
操作符一起使用这些函数,也可以在为 $group
操作符定义_id时使用。
最简单的重塑是把字段重命名并生成新字段,也可以通过修改或创建一个新文档来重塑一个文档。
示例为创建一个同时包含两个字段first和last名为name的字段。
db.users.aggregate([
$match:username:'kbanker',
$project:name:first:'$first_name',
last:'$last_name'
])
12、除了重命名或者重新构建文档字段外,也可以使用不同的重塑函数来创建新的字段。重塑函数根据处理数据类型的不同进行分组:字符串、算数运算、日期、逻辑、集合、其他类型。
13、字符串函数允许操作字符串:
函数 | 作用 |
---|---|
$concat | 连接2个或者更多字符串为一个字符串 |
$strcasecmp | 大小写敏感的比较,返回数字 |
$substr | 获取字符串的子串 |
$toLower | 转换为小写字符串 |
$toUpper | 转换为大写字符串 |
18、算术运算符函数
函数 | 作用 |
---|---|
$add | 求和 |
$divide | 除法 |
$mod | 求余数 |
$multiply | 乘积 |
$subtract | 减法 |
19、日期函数
函数 | 作用 |
---|---|
$dayOfYear | 一年365天中某一天 |
$dayOfMouth | 一月中的某一天 |
$dayOfWeek | 一周中的某一天,1表示周日 |
$year | 日期的年份 |
$mouth | 日期的月份,1~12 |
$week | 一年中的某一周,0~53 |
$hour | 日期中的小时,0~23 |
$minute | 日期中的分钟,0~59 |
$second | 日期中的秒,0~59 |
$millisecond | 日期中的毫秒,0~999 |
20、逻辑函数
函数 | 作用 |
---|---|
$and true | 与操作,如果数组里所有值都为true,则返回true |
$cmp | 如果两个数相等就返回0 |
$cond if...then...else | 条件逻辑 |
$eq | 两个值是否相等 |
$gt | 值1是否大于值2 |
$gte | 值1是否大于等于值2 |
$ifNull | 把null值/表达式转换为特定的值 |
$lt | 值1是否小于等于值2 |
$lte | 值1是否不等于值2 |
$ne | 值1是否不等于值2 |
$not | 取反操作 |
$or | 或,如果数组中有一个true,就返回true |
21、集合函数
函数 | 作用 |
---|---|
$setEquals | 如果两个集合的元素完全相同,则为true |
$setIntersection | 返回两个集合的公告元素 |
$setDifference | 返回第一个集合中与第二个集合不同的元素 |
$setUnion | 合并集合 |
$setIsSubset | 如果第二个集合为第一个集合的子集,则为true |
$setElementTrue | 如果某个集合元素为true,则为true |
$allElementsTrue true | 如果所有集合元素都为true,则为true |
22、其他函数
函数 | 作用 |
---|---|
$meta | 文本搜索 |
$size | 返回数组大小 |
$map | 对数组的每个成员应用表达式【允许处理数组并对数组元素执行函数生成性的数组】 |
$let | 定义表达式内使用的变量【允许使用临时变量】 |
$literal | 返回表达式的值,而不评估它【避免初始化字段值为0,1,$ 】 |
23、影响聚合管道性能的关键点
- 尽早在管道里尝试减少文档的数量和大小
- 索引只能用于
$match
和$sort
操作,而且可以大大加速查询 - 在管道使用
$match
和$sort
之外的操作符后不能使用索引 - 如果使用分片(分片存储大数据集合),则
$match
和$project
会在单独的片上执行。一旦使用其他操作符,其余的管道将会在主要片上执行。
24、aggregate()传递第二个参数来指定集合调用
explain()
运行管道并且只返回管道处理详细信息【某个索引是否被显示、索引扫描的范围、哪个索引可以限制查询等】allowDiskUse
使用磁盘存储数据【可能会降低管道性能】cursor
指定初始批处理的大小
db.collection.aggregate(pipeline,additionalOptions)
additionalOptions是可选的JSON对象,可以传递给aggregate()函数。additionalOptions的参数如下:
explain:true,allowDiskUse:true,cursor:batchSize:n
25、管道返回的光标支持的调用:
cursor.hasNext()
确定结果集是否包含下一个元素cursor.next()
返回结果集的下一个文档cursor.toArray()
以数组返回结果cursor.forEach()
遍历结果集的每一行cursor.map()
遍历结果集的每一行,返回一个结果数组cursor.itcount()
返回结果数量(仅做调试)cursor.pretty()
显示格式化结果的数组
26、光标允许处理大规模数据流,允许返回少量文档结构的时候处理大的结果集,可以减少一次性处理数据所需的内存,还可以限制服务端返回的文档数量。toArray()
和 pretty()
则立即读入内存。
27、map-reduce
最早版本MongoDB提供的聚合功能,然而比聚合框架慢得多。第一步是编写map函数,目睹是定义分组操作键,打包索引需要计算的数据。emit()
是该步骤必调方法,第一个参数是分组关键值,第二个是包含值的要处理的文档。第二步是reduce函数,确保这些值按照期望的方式进行聚合处理,然后返回单个字【第一个步只有一个值,该函数不会调用】。
以上是关于笔记的主要内容,如果未能解决你的问题,请参考以下文章