目录
1、管道概念:
2、管道语法:
3、管道实例:
(1)实例一:count
(2)实例二:group分组
(3)实例三:group全部
(4)实例四:limit
(5)实例五:in外联
(6)实例六:match过滤
(7)实例七:out结果输出集合
(8)实例八:project过滤显示字段
(9)实例九:skip跳过文档
(10)实例十:sort排序
4、管道思想:
管道在Unix和Linux中一般用于将当前命令的输出结果作为下一个命令的参数。
MongoDB的聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作是可以重复的。
表达式:处理输入文档并输出。表达式是无状态的,只能用于计算当前聚合管道的文档,不能处理其它的文档。
基本用法如下:
db.collection.aggregate( [ {
语法中的stage如下:
名称 |
描述 |
$addFields |
将新的字段添加到文档中,输出的文档包含已经存在的字段和新加入的字段。 |
$bucket |
根据指定的表达式和存储区边界将传入文档分组到称为buckets的组中。 |
$bucketAuto |
根据指定的表达式将传入文档分类到特定数量的组(称为buckets)。存储区边界自动确定,试图将文档均匀分布到指定数量的buckets中。 |
$collStats |
返回有关集合或视图的统计信息。 |
$count |
返回聚合管道的计数。 |
$currentOp |
返回有关MongoDB部署的活动和/或休眠操作的信息。 |
$facet |
在同一组输入文档中的单个阶段内处理多个聚合流水线。支持创建多方面的聚合,能够在单个阶段中跨多个维度或方面表征数据。 |
$geoNear |
根据地理空间点的接近度返回有序的文档流。包含地理空间数据的$ match,$ sort和$ limit功能。输出文件包含一个额外的距离字段,并可包含位置标识符字段。 |
$graphLookup |
对集合执行递归搜索。为每个输出文档添加一个新的数组字段,其中包含该文档的递归搜索的遍历结果。 |
$group |
按指定的标识符表达式输入文档,并将累加器表达式(如果指定)应用于每个组。消耗所有输入文档并为每个不同的组输出一个文档。输出文件只包含标识符字段,如果指定了,则包含累积字段。 |
$indexStats |
返回有关使用集合中每个索引的统计信息。 |
$limit |
将未修改的前n个文档传递到管道,其中n是指定的限制。对于每个输入文档,输出一个文档(前n个文档)或零文档(前n个文档之后)。 |
$listLocalSessions |
列出最近在当前连接的mongos或mongod实例中使用的所有活动会话。这些会话可能尚未传播到system.sessions集合。 |
$listSessions |
列出所有活动时间足以传播到system.sessions集合的所有会话。 |
$lookup |
将左外连接执行到同一数据库中的另一个集合,以过滤“已连接”集合中的文档进行处理。 |
$match |
过滤文档流,只允许匹配的文档未经修改地传递到下一个管道阶段。 $ match使用标准的MongoDB查询。对于每个输入文档,输出一个文档(匹配)或零个文档(不匹配)。 |
$out |
将聚合管道的结果文档写入集合。要使用$ out阶段,它必须是管道中的最后一个阶段。 |
$project |
重新设计流中的每个文档,例如添加新字段或删除现有字段。对于每个输入文档,输出一个文档。 |
$redact |
根据存储在文档本身中的信息限制每个文档的内容,重新整形流中的每个文档。包含$ project和$ match的功能。可用于实施字段级别的编校。对于每个输入文档,输出一个或零个文档。 |
$replaceRoot |
用指定的嵌入式文档替换文档。该操作将替换输入文档中的所有现有字段,包括_id字段。指定嵌入在输入文档中的文档以将嵌入式文档提升到顶层。 |
$sample |
从其输入中随机选择指定数量的文档。 |
$skip |
跳过前n个文档,其中n是指定的跳过编号,并将未修改的其余文档传递到管道。对于每个输入文档,输出零文档(对于前n个文档)或一个文档(如果在前n个文档之后)。 |
$sort |
通过指定的排序键对文档流进行重新排序。只有订单改变了;文件保持不变。对于每个输入文档,输出一个文档。 |
$sortByCount |
根据指定表达式的值对传入文档分组,然后计算每个不同组中文档的数量。 |
$unwind |
从输入文档解构数组字段以输出每个元素的文档。每个输出文档用一个元素值替换数组。对于每个输入文档,输出n个文档,其中n是数组元素的数量,对于空数组可以为零。 |
代码:
db.scores.aggregate(
[
{
$match: {
score: {
$gt: 80
}
}
},
{
$count: "passing_scores"
}
]
)
意义:
匹配score字段大于80分的文档,然后计算数量,重命名为passing_scores输出。
结果:
{ "passing_scores" : 4 }
代码:
db.sales.aggregate(
[
{
$group : {
_id : { month: { $month: "$date" }, day: { $dayOfMonth: "$date" }, year: { $year: "$date" } },
totalPrice: { $sum: { $multiply: [ "$price", "$quantity" ] } },
averageQuantity: { $avg: "$quantity" },
count: { $sum: 1 }
}
}
]
)
意义:
将文档根据时间(相同的年月日)分组,并计算其总价格(价格*数量求和),平均的数量,每个分组有多少个文档。
结果:
{ "_id" : { "month" : 3, "day" : 15, "year" : 2014 }, "totalPrice" : 50, "averageQuantity" : 10, "count" : 1 }
{ "_id" : { "month" : 4, "day" : 4, "year" : 2014 }, "totalPrice" : 200, "averageQuantity" : 15, "count" : 2 }
{ "_id" : { "month" : 3, "day" : 1, "year" : 2014 }, "totalPrice" : 40, "averageQuantity" : 1.5, "count" : 2 }
代码:
db.sales.aggregate(
[
{
$group : {
_id : null,
totalPrice: { $sum: { $multiply: [ "$price", "$quantity" ] } },
averageQuantity: { $avg: "$quantity" },
count: { $sum: 1 }
}
}
]
)
意义:
计算所有文档的总价格(价格*数量求和),平均的数量,有多少个文档。
结果:
{ "_id" : null, "totalPrice" : 290, "averageQuantity" : 8.6, "count" : 5 }
代码:
db.article.aggregate(
{ $limit : 5 }
);
意义:
article只返回前5个文档。
代码:
db.orders.aggregate([
{
$lookup:
{
from: "inventory",
localField: "item",
foreignField: "sku",
as: "inventory_docs"
}
}
])
意义:
集合orders中item字段与集合inventory中sku字段进行关联,关联上的信息存储在inventory_docs字段中进行展示。
结果:
{
"_id" : 1,
"item" : "almonds",
"price" : 12,
"quantity" : 2,
"inventory_docs" : [
{ "_id" : 1, "sku" : "almonds", "description" : "product 1", "instock" : 120 }
]
}
{
"_id" : 2,
"item" : "pecans",
"price" : 20,
"quantity" : 1,
"inventory_docs" : [
{ "_id" : 4, "sku" : "pecans", "description" : "product 4", "instock" : 70 }
]
}
代码:
db.articles.aggregate(
[ { $match : { author : "dave" } } ]
);
意义:
集合articles中author字段值为dave的文档。
结果:
{ "_id" : ObjectId("512bc95fe835e68f199c8686"), "author" : "dave", "score" : 80, "views" : 100 }
{ "_id" : ObjectId("512bc962e835e68f199c8687"), "author" : "dave", "score" : 85, "views" : 521 }
代码:
db.books.aggregate( [
{ $group : { _id : "$author", books: { $push: "$title" } } },
{ $out : "authors" }
] )
意义:
将books的author字段分类并作为_id字段的内容,将相同作者的title都push到books字段中,将其插入authors表中。
结果:
{ "_id" : "Homer", "books" : [ "The Odyssey", "Iliad" ] }
{ "_id" : "Dante", "books" : [ "The Banquet", "Divine Comedy", "Eclogues" ] }
代码:
db.books.aggregate( [
{ $project : { title : 1 , author : 1 }
} ] )
意义:
结果只显示:_id,title,author字段。
结果:
{ "_id" : 1, "title" : "abc123", "author" : { "last" : "zzz", "first" : "aaa" } }
代码:
db.article.aggregate(
{ $skip : 5 }
);
意义:
跳过前5个文档,从第6个文档开始显示。
代码:
db.users.aggregate([
{ $sort : { age : -1, posts: 1 } }
])
意义:
集合users中按照age字段降序排列,posts字段升序排列。
-1表示降序排列,1表示升序排列。
管道实例中列举了常用的管道实例,实际应用一般都是根据业务,对多种管道实例进行组合使用,不用的业务有需求,对应的不同的管道实例组合先后顺序。
管道思想就是通过不同的管道实例组合,一步步对数据进行相关的操作,最终获取想要的结果数据。就是要根据业务灵活的对不同的管道实例进行组合应用的一种思想。