首页 > 数据库 > > mongo.Aggregate.倚天剑.剑走偏锋
热爱武侠的人一定读过金庸老先生写的“倚天屠龙记”,宝刀屠龙,号令天下,莫敢不从,前4篇「Mongo存储和性能优化」所展示的,可以说是屠龙刀,而现在我们即将描述的Aggregate就是倚天剑,倚天不出,谁也争锋..
倚天剑里面所藏武功,就是九阴白骨爪,下面让我们一起来修行这个高深莫测的武功,废话就到此为止,开始练功。
使用聚合框架可以对集合中文档进行变化和组合,可以用多个构件创建一个管道,用于对一连串的文档进行处理,构件有筛选,投影,分组,排序等。
db.collection.aggregate(pipeline,options) , pipeline 「数据的聚合操作」,Options「explain,allowDiskUse,cursor,maxTimeMS,bypassDocumentValidation,readConcern」 具体的详细信息,点击查看官网文
下面着重介绍其中的管道操作符号:
简介:通过指定的条件来过滤文档,然后传给下一个管道
语法:{ $match: { <query> } }
数据源
{ "_id" : ObjectId("512bc95fe835e68f199c8686"), "author" : "dave", "score" : 80, "views" : 100 }
{ "_id" : ObjectId("512bc962e835e68f199c8687"), "author" : "dave", "score" : 85, "views" : 521 }
{ "_id" : ObjectId("55f5a192d4bede9ac365b257"), "author" : "ahn", "score" : 60, "views" : 1000 }
{ "_id" : ObjectId("55f5a192d4bede9ac365b258"), "author" : "li", "score" : 55, "views" : 5000 }
{ "_id" : ObjectId("55f5a1d3d4bede9ac365b259"), "author" : "annT", "score" : 60, "views" : 50 }
{ "_id" : ObjectId("55f5a1d3d4bede9ac365b25a"), "author" : "li", "score" : 94, "views" : 999 }
{ "_id" : ObjectId("55f5a1d3d4bede9ac365b25b"), "author" : "ty", "score" : 95, "views" : 1000 }
查询语句
db.articles.aggregate(
[ { $match : { author : "dave" } } ]
);
结果:
{ "_id" : ObjectId("512bc95fe835e68f199c8686"), "author" : "dave", "score" : 80, "views" : 100 }
{ "_id" : ObjectId("512bc962e835e68f199c8687"), "author" : "dave", "score" : 85, "views" : 521 }
参考文章:
$match (aggregation)
简介:传给下一个管道所需要的字段,字段包含输入文档存在的字段和新的计算字段
语法:{ $project: { <specification(s)> } }
数据源
{
"_id" : 1,
title: "abc123",
isbn: "0001122223334",
author: { last: "zzz", first: "aaa" },
copies: 5
}
查询语句
db.books.aggregate( [ { $project : { title : 1 , author : 1 } } ] )
输出结果
{ "_id" : 1, "title" : "abc123", "author" : { "last" : "zzz", "first" : "aaa" } } 参考文章:
$project (aggregation)
简介:按照指定的表达式来对文档进行分组,然后按照每一个分组传给下一个管道,最后输出对文档包含_id作为分组对Key,输出对文档也包含计算的字段的值。
语法:{ $group: { _id: <expression>, <field1>: { <accumulator1> : <expression1> }, ... } }
数据源
{ "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2, "date" : ISODate("2014-03-01T08:00:00Z") }
{ "_id" : 2, "item" : "jkl", "price" : 20, "quantity" : 1, "date" : ISODate("2014-03-01T09:00:00Z") }
{ "_id" : 3, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-03-15T09:00:00Z") }
{ "_id" : 4, "item" : "xyz", "price" : 5, "quantity" : 20, "date" : ISODate("2014-04-04T11:21:39.736Z") }
{ "_id" : 5, "item" : "abc", "price" : 10, "quantity" : 10, "date" : ISODate("2014-04-04T21:23:13.331Z") }
查询语句
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 }
参考文章
$group (aggregation)
简介:将输入文档中的数组,分割成对应的一个文档,数组中的一个值对应一个文档
语法:{
$unwind:
{
path: <field path>,
includeArrayIndex: <string>,
preserveNullAndEmptyArrays: <boolean>
}
}
数据源
{ "_id" : 1, "item" : "ABC1", sizes: [ "S", "M", "L"] }
查询语句
db.inventory.aggregate( [ { $unwind : "$sizes" } ] )
输出结果
{ "_id" : 1, "item" : "ABC1", "sizes" : "S" }
{ "_id" : 1, "item" : "ABC1", "sizes" : "M" }
{ "_id" : 1, "item" : "ABC1", "sizes" : "L" }参考文章
https://docs.mongodb.com/manual/reference/operator/aggregation/unwind/语法:{ $limit: <positive integer> }
db.article.aggregate(
{ $limit : 5 }
);参考文章:
$limit (aggregation)
简介:跳过指定数量的文档,传递剩余的文档到下一个管道
语法:{ $skip: <positive integer> }
db.article.aggregate(
{ $skip : 5 }
);参考文章
$skip (aggregation)
简介:排序所有的文档传给下一个管道
语法 :{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } }
db.users.aggregate(
[
{ $sort : { age : -1, posts: 1 } }
]
)参考文章
$sort (aggregation)
简介:在同一个数据库执行左外连接,来过滤相关的文档,传递给下一个管道
语法:{
$lookup:
{
from: <collection to join>,
localField: <field from the input documents>,
foreignField: <field from the documents of the "from" collection>,
as: <output array field>
}
}
数据源:
db.orders.insert([
{ "_id" : 1, "item" : "almonds", "price" : 12, "quantity" : 2 },
{ "_id" : 2, "item" : "pecans", "price" : 20, "quantity" : 1 },
{ "_id" : 3 }
])
db.inventory.insert([
{ "_id" : 1, "sku" : "almonds", description: "product 1", "instock" : 120 },
{ "_id" : 2, "sku" : "bread", description: "product 2", "instock" : 80 },
{ "_id" : 3, "sku" : "cashews", description: "product 3", "instock" : 60 },
{ "_id" : 4, "sku" : "pecans", description: "product 4", "instock" : 70 },
{ "_id" : 5, "sku": null, description: "Incomplete" },
{ "_id" : 6 }
])
查询语句:
db.orders.aggregate([
{
$lookup:
{
from: "inventory",
localField: "item",
foreignField: "sku",
as: "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 }
]
}
{
"_id" : 3,
"inventory_docs" : [
{ "_id" : 5, "sku" : null, "description" : "Incomplete" },
{ "_id" : 6 }
]
}参考文章
$lookup (aggregation)
简介:统计文档的数量传递给下一个管道
语法:{ $count: <string> }
数据源
{ "_id" : 1, "subject" : "History", "score" : 88 }
{ "_id" : 2, "subject" : "History", "score" : 92 }
{ "_id" : 3, "subject" : "History", "score" : 97 }
{ "_id" : 4, "subject" : "History", "score" : 71 }
{ "_id" : 5, "subject" : "History", "score" : 79 }
{ "_id" : 6, "subject" : "History", "score" : 83 }
查询语句
db.scores.aggregate(
[
{
$match: {
score: {
$gt: 80
}
}
},
{
$count: "passing_scores"
}
]
)
输出结果
{ "passing_scores" : 4 }参考文章
$count (aggregation)
简介:根据文档本身存储的信息来限制文档
语法:{ $redact: <expression> }
数据源
{
_id: 1,
title: "123 Department Report",
tags: [ "G", "STLW" ],
year: 2014,
subsections: [
{
subtitle: "Section 1: Overview",
tags: [ "SI", "G" ],
content: "Section 1: This is the content of section 1."
},
{
subtitle: "Section 2: Analysis",
tags: [ "STLW" ],
content: "Section 2: This is the content of section 2."
},
{
subtitle: "Section 3: Budgeting",
tags: [ "TK" ],
content: {
text: "Section 3: This is the content of section3.",
tags: [ "HCS" ]
}
}
]
}
查询语句
var userAccess = [ "STLW", "G" ];
db.forecasts.aggregate(
[
{ $match: { year: 2014 } },
{ $redact: {
$cond: {
if: { $gt: [ { $size: { $setIntersection: [ "$tags", userAccess ] } }, 0 ] },
then: "$$DESCEND",
else: "$$PRUNE"
}
}
}
]
);
输出结果
{
"_id" : 1,
"title" : "123 Department Report",
"tags" : [ "G", "STLW" ],
"year" : 2014,
"subsections" : [
{
"subtitle" : "Section 1: Overview",
"tags" : [ "SI", "G" ],
"content" : "Section 1: This is the content of section 1."
},
{
"subtitle" : "Section 2: Analysis",
"tags" : [ "STLW" ],
"content" : "Section 2: This is the content of section 2."
}
]
}参考文章
$redact (aggregation)
九阴白骨爪果真是门邪恶的武功,头痛无比,夜已深,在写非得走火入魔,下期再见 九阴白骨爪.横扫千军.....
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31537575/viewspace-3126810/ ,如需转载,请注明出处,否则将追究法律责任。