聚合
特点:从多个文档分组,在各个分组内进行多种操作,并返回结果
聚合有三种方式
- aggregation pipeline 管道聚合
- map-reduce
- single purpose aggregation methods 单一聚合
管道聚合 目前我常用的方式
文档分别通过多级管道,管道内可以进行任何操作,并最终返回结果
例如:
db.admins.aggregate([
{
$match:{ //do somethings }
},
{
$group: { //do somethings }
}
])
管道聚合常用的操作符
- $group
- $match
- $lookup
- $project
- $sort
- $skip
- $limit
…….
管道聚合官方文档
管道聚合优化
预测优化
- 原因:聚合会将整个集合全部放入管道中,这样会降低速度而且可能会超过内存限制,所以如果只需要集合中部分数据,那么仅仅传入这些数据就可以
- 操作:主要是操作符为: $match 和 $limit 放在一般操作的前面,减少后续的数据量
合并优化
- 同操作符的合并
- $lookup + $unwind 的合并
聚合管道的限制
结果集大小限制
BSON的限制:每个document不超过16MB,如果超过了,在管道内部不会报错,但是返回结果集时会报错
内存限制
管道内部允许占用100MB的RAM,超过该内存时,mongodb会抛出错误,如果想使用大数据集合,可以使用 allowDiskUse选项开启管道阶段,数据写入临时文件
单一聚合
提供了 db.collection.count() 和 db.collection.distinct()
文本索引
特点:
- 快速执行文本查询操作,支持多种匹配
- 支持所有字符串及字符串的数组
- 必须含有文本索引,且文本索引唯一
- 使用$test和$search检索 $meta打分
创建文本索引
db.collection.createIndex({key:'text',key1:'text'....})
查找
db.collection.find({$test:{$search:''}})
一般检索 匹配任意为 name或age或sex的数据
db.collection.find({$test:{$search:'name age sex'}})
精确检索 匹配任意为 name或 age sex的数据
db.collection.find({$test:{$search:'name \'age sex\''}})
排除检索 匹配任意为 name或age且无sex的数据
db.collection.find({$test:{$search:'name age -sex'}})
计分:score根据匹配程度来打分
db.collection.find({$test:{$search:'name age sex'},score:{$meta: "textScore"}})
聚合管道使用
- 包含了$text 的 $match 阶段必须是管道中的 第一个 阶段。
- 操作符 $text 只能在阶段中出现一次
- 操作符 $text 不能出现在 $or 和 $not 表达式中
- 默认地,文本搜索不会返回按照匹配得分的顺序返回匹配文档。可以选择在 $sort 阶段使用 $meta 聚合表达式。