您的位置:首页 > 数据库 > Mongodb

【MongoDB】Aggregation Pipeline——聚合管道

2017-11-09 20:36 381 查看
MongoDB提供聚合管道技术进行处理输入的数据,数据经过一个一个的stage,每个stage将数据处理后的结果传递给下一个stage,最终得到多重处理后的结果。

Aggregate提供了多种stage可供选择,match、sort、limit、limit等。对于嵌套数据的处理可以在Aggregate中实现,减少在代码上的编写。

一、优化策略

1.1手动优化

1.match、sort 可以使用索引

2.geoNear必须是管道的第一个stage3.match、limit、skip 尽可能早的使用

1.2 自动优化阶段

Aggregate在执行聚合操作之前会有一个自动优化阶段,它会在小范围内优化stage队列。

[{$sort:{}},{$match:{}}] 	-->	[{$match:{}},{$sort:{}}]
[{$skip:n},{$limit:m}]	-->	[{$limit:m},{$skip:n}]
[{$project:{}},{$limit:m},{$skip:n}]	-->	[{$limit:m},{$skip:n},{$project:{}}]

对于skip和limit测试时,发现不同顺序时,结果不一致。似乎优化并没有成功


上述情况都是在紧邻着出现时,才会做优化处理。

1.3 重复的stage处理

[{$limit:100},{$limit:10}]		-->	[{$limit:10}]
[{$skip:5},{$skip:2}]		-->	[{$skip:7}]


当队列中出现多个limit、skip时,等价于后面的stage。

1.4 惰性执行

聚合管道在对数据处理时,采用惰性执行,它不会扫描所有的字段(包含嵌套字段),只有使用到的字段才会进行扫描。

二 Stages

MongoDB的聚合管道是由stage组成的,当文档通过管道时每一个stage都对文档进行处理。对于输入的文档,stage可以产生新的文档或者过滤文档,但是stage不需要为它产生一个输出文档。管道中可以使用多个stage。原文链接:https://docs.mongodb.com/manual/core/aggregation-pipeline/

2.1 stages

原文链接:https://docs.mongodb.com/manual/reference/operator/aggregation/#aggregation-pipeline-operator-reference

$match

过滤文档,将匹配成功地文档传递给下一个stage。

demo:
Db.data.aggregaet([
{$macth:{‘_id’:1}}
])


$project

拆分重组JSONP对象,保留需要的字段

demo
Db.data.aggregate([
{$project:{_id:’$_id’,name:1,age:’$age’}}
])


注意:$_id指向原文档的_id字段。1,表示保留原文档的字段

$group

分组查询。参照元素即输出元素,_id中可以设置分组的依据,其余自定义字段必须是可累加的字段(sum,push)

demo
db.data.aggregate([{$group:{_id:{name:"$name"},num:{$sum:1},money:{$sum:1.5}])
{ "_id" : { "name" : "apple" }, "num" : 3, "money" : 4.5 }


$redact

编辑文档,对嵌套文档选择性编辑

可接受返回值

> $$DESCEND	可以编辑当前文档中的嵌套文档
> $$PRUNE        不可以编辑当前文档及其包含的嵌套文档
> $$KEEP      保持当前文档状态


常与表达式$cond一起使用

db.data.aggregate([
{$match:{title:'123 Department Report'}},
{$redact:{
$cond:{
if:{
$gt:[{$size:['$tags']},1]
},
then:'$$DESCEND',
else:'$$PRUNE'
}
}}
])


$unwind

展开数组,将一条带有内嵌的数组的数据展开成多条数据。

$sample

随机选择N条数据

$geoNear

二维地理信息

$lookup

联合查询,类似与关系数据库的左查询

{$lookup:{
from:”collection name”,
localField:”local field name”,
foreignField:”foreign field name”,
as:”output field”   //输出是一个数组
}}


$out

将聚合结果输入到一个新的集合(若集合已经存在,会覆盖集合中原有数据)

$out:’out colloection name’


$indexStats

查看索引的信息,每个集合都有一个默认的索引

db.data.aggregate( [ { $indexStats: { } } ] )


$bucket

统计连续区间的数据的数量,左闭右开

db.summary.aggregate([{
$bucket:{
groupBy:'$time',
boundaries:['2017-10','2017-11'],
default:'other',
output:{
"count": { $sum: 1 },
'datas':{$push:'$data'}
}
}
}])


$facet

在它里面可以使用多个stage,输出是一个对象,对象中的每个字段都是一个数组。

db.summary.aggregate([{
$facet:{
datas:[
{$unwind:'$data'}
],
time:[
{$group:{_id:{time:'$time'}}}
]
}
}])


$sortByCount

倒序输出,等价于group和sort的组合使用

$addFields

增加多个字段

db.summary.aggregate([
{
$addFields:{
size:{$size:'$data'}
}
}
])


$replaceRoot

替换对象到根路径,必须是对象{}

db.summary.aggregate([
{$unwind:'$data'},
{$replaceRoot:{newRoot:'$data'}}
])


总结:

聚合管道在处理嵌套数据时,可以对一个文档进行多重处理。输入数据为一条,多次处理,每次处理后将结果直接传递给下一个stage,最终得到一个输出结果;

在处理嵌套文档时提供很大遍历;

提供两个集合之间联合查询的接口。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  mongodb aggregatio pipe