聚合查询中又分为:聚合阶段,和聚合操作
聚合阶段主要对文档进行:选择,投影,分组,加减字段,排序,连接
聚合操作是用来实现聚合阶段的功能。 如为了实现选择,可以使用数学表达式
关于查询匹配分两种:
这种方式,不能进行计算:{field:{$op, value}}
{$expr:{$op:[f1,f2..]}}支持复杂数值运算,使用逻辑and or可以支持多级匹配
数据u,v两个集合操作
1.匹配 满足条件的行才被选出来 match
2.投影 选择需要和不需要的字段 project
3.数组 选择数组中的文档的字段, 对数组进行范围截取,数组摊平unwind, 求大小, 在数组中in
4.添加新字段 set add
5.两表连接u.FieldA=v.FieldA lookup, graphLookup
6.限制输出数量limit
7.排序 sort
8.分段 bucket,按某一个字段的值进行分段
9.分组 group, 按某一个字段进行分组
10.求合sum,平均average,计数count,最大max, 最小min,
11.过滤、filter, 字段A过滤后变成字段B
12.绑定值到变量 let
13.比较:> >= < <=
14.逻辑:and or not nor
15.数学运算: + - * / abs acos achsh cos sin tan 连接cat 子串substr 指数 对数 开方 取模
16.取整:ceil floor 四舍五入round
17.日期操作:字符串到日期,日期到字符串。取日期中的年月日小时
18.随机,第一个first
19. 数字,字符串转换 toDate, toDecimal toDouble toInt toLong toString toLower strlen** 分隔split trim
20. 合并集合merge
21.表达式求值expr,可以使用2元操作$op:[f,g]
操作符分为1元,2元,3元,n元
1元操作符:{field:{$op, value}}, 如存在exists, 非not
2元操作符:{field1:{$op, field2}}, 如> <
{$op:[field1, field2]}, 如+, -, >, <
3元操作符:$cond
n元操作符:{$op:valueName} 如sum, count
db.stu.insertMany([
{"name":"wyg","age":28, "score":98},
{"name":"hy","age":28, "score":40},
{"name":"wl","age":27, "score":90},
{"name":"seq","age":28, "score":66},
{"name":"zj","age":18, "score":80},
{"name":"adson","age":28, "score":98},
{"name":"jack","age":30, "score":83},
{"name":"frac","age":32, "score":76}
])
//聚合操作,使用groupby
db.stu.aggregate([
{
"$group": {
"_id":"$age",
"scores":{"$addToSet":"$score"}
}
}
])
//计数
db.stu.aggregate([
{
"$count":"numOfPeople"
}
])
//{ "numOfPeople" : 8 }
//添加新字段
db.stu.aggregate(
[
{
"$facet": {
"name":[{"$project":{"name":1}}],
"sumOfAge":[{$group:{_id:0,"sum":{"$sum":"$age"}}}],
}
}
]).pretty()
//添加新字段
db.stu.aggregate([
{
"$set":{
"sumOfScore":{
"$sum":"$score"
}
}
}
])
//分组并添加新字段
db.stu.aggregate(
[
{
"$group": {
_id:0,
sumOfAge:{$sum:"$age"},
sumOfScore:{$sum:"$score"}
}
},
{
"$project":{
"_id":0,
"sumOfAge":1,
"sumOfScore":1
}
}
])
//抽影并添加新字段
db.stu.aggregate([{"$project":{"_id":0, "name":1, "total":{$add:['$age','$score']}}}])
//按区间分组
db.stu.aggregate([
{
$bucket:{
groupBy:"$score",
boundaries:[0, 60, 70, 80, 90, 100],
default:"Other",
output:{
count:{$sum:1},
}
}
}
])
db.artists.insertMany([
{ "_id" : 1, "last_name" : "Bernard", "first_name" : "Emil", "year_born" : 1868, "year_died" : 1941, "nationality" : "France" },
{ "_id" : 2, "last_name" : "Rippl-Ronai", "first_name" : "Joszef", "year_born" : 1861, "year_died" : 1927, "nationality" : "Hungary" },
{ "_id" : 3, "last_name" : "Ostroumova", "first_name" : "Anna", "year_born" : 1871, "year_died" : 1955, "nationality" : "Russia" },
{ "_id" : 4, "last_name" : "Van Gogh", "first_name" : "Vincent", "year_born" : 1853, "year_died" : 1890, "nationality" : "Holland" },
{ "_id" : 5, "last_name" : "Maurer", "first_name" : "Alfred", "year_born" : 1868, "year_died" : 1932, "nationality" : "USA" },
{ "_id" : 6, "last_name" : "Munch", "first_name" : "Edvard", "year_born" : 1863, "year_died" : 1944, "nationality" : "Norway" },
{ "_id" : 7, "last_name" : "Redon", "first_name" : "Odilon", "year_born" : 1840, "year_died" : 1916, "nationality" : "France" },
{ "_id" : 8, "last_name" : "Diriks", "first_name" : "Edvard", "year_born" : 1855, "year_died" : 1930, "nationality" : "Norway" }
])
//按区间分组,并添加新字段
db.artists.aggregate( [
// First Stage
{
$bucket: {
groupBy: "$year_born", // Field to group by
boundaries: [ 1840, 1850, 1860, 1870, 1880 ], // Boundaries for the buckets
default: "Other", // Bucket id for documents which do not fall into a bucket
output: { // Output for each bucket
"count": { $sum: 1 },
"artists" :
{
$push: {
"name": { $concat: [ "$first_name", " ", "$last_name"] },
"year_born": "$year_born"
}
}
}
}
},
// Second Stage
{
$match: { count: {$gt: 3} }
}
] )
//计数
db.orders.aggregate({$count:"num"})
//分组求合
db.orders.aggregate([{$group:{_id:"$status","num":{$sum:1}}}])
db.orders.findOne()
db.sales.insertMany([
{ "_id" : 1, "item" : "abc", "price" : NumberDecimal("10"), "quantity" : NumberInt("2"), "date" : ISODate("2014-03-01T08:00:00Z") },
{ "_id" : 2, "item" : "jkl", "price" : NumberDecimal("20"), "quantity" : NumberInt("1"), "date" : ISODate("2014-03-01T09:00:00Z") },
{ "_id" : 3, "item" : "xyz", "price" : NumberDecimal("5"), "quantity" : NumberInt( "10"), "date" : ISODate("2014-03-15T09:00:00Z") },
{ "_id" : 4, "item" : "xyz", "price" : NumberDecimal("5"), "quantity" : NumberInt("20") , "date" : ISODate("2014-04-04T11:21:39.736Z") },
{ "_id" : 5, "item" : "abc", "price" : NumberDecimal("10"), "quantity" : NumberInt("10") , "date" : ISODate("2014-04-04T21:23:13.331Z") },
{ "_id" : 6, "item" : "def", "price" : NumberDecimal("7.5"), "quantity": NumberInt("5" ) , "date" : ISODate("2015-06-04T05:08:13Z") },
{ "_id" : 7, "item" : "def", "price" : NumberDecimal("7.5"), "quantity": NumberInt("10") , "date" : ISODate("2015-09-10T08:43:00Z") },
{ "_id" : 8, "item" : "abc", "price" : NumberDecimal("10"), "quantity" : NumberInt("5" ) , "date" : ISODate("2016-02-06T20:20:13Z") },
])
//按多个字段分组
db.sales.aggregate([{$group:{
"_id":{"day":{"$dayOfYear":"$date"},"year":{"$year":"$date"}},
"itemSold":{"$addToSet":"$item"}
}}])
//计数
db.sales.aggregate([
{
$group:{
_id:null,
count:{$sum:1}
}
}
])
//分组计算并过滤
db.sales.aggregate([
{
$group:{
_id:'$item',
totalSaleAmount:{
$sum:{
$multiply:["$price","$quantity"]
}
}
}
},
{
$match : {
"totalSaleAmount":{
$gte : 100
}
}
}
])
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"
}
}
])
db.classes.insert( [
{ _id: 1, title: "Reading is ...", enrollmentlist: [ "giraffe2", "pandabear", "artie" ], days: ["M", "W", "F"] },
{ _id: 2, title: "But Writing ...", enrollmentlist: [ "giraffe1", "artie" ], days: ["T", "F"] }
])
db.members.insert( [
{ _id: 1, name: "artie", joined: new Date("2016-05-01"), status: "A" },
{ _id: 2, name: "giraffe", joined: new Date("2017-05-01"), status: "D" },
{ _id: 3, name: "giraffe1", joined: new Date("2017-10-01"), status: "A" },
{ _id: 4, name: "panda", joined: new Date("2018-10-11"), status: "A" },
{ _id: 5, name: "pandabear", joined: new Date("2018-12-01"), status: "A" },
{ _id: 6, name: "giraffe2", joined: new Date("2018-12-01"), status: "D" }
])
//左外连接两个表
db.classes.aggregate([
{
$lookup:
{
from: "members",
localField: "enrollmentlist",
foreignField: "name",
as: "enrollee_info"
}
}
])
db.inventory.insertOne({ "item" : "ABC1", sizes: [ "S", "M", "L"] })
db.inventory.aggregate( [ { $unwind : "$sizes" },{$project:{_id:0}} ] )
db.userA.insertMany([
{"username":"wyg", "addr":"shenzheng", "tel":"653245", "course":"CS"},
{"username":"hy", "addr":"wuhan", "tel":"18365822", "course":"PE"},
{"username":"frac", "addr":"beijing", "tel":"11223", "course":"MATH"}
])
//字段存在
db.stu.find({"tel":{$exists:1}})
db.stu.aggregate([{
"$lookup": {
"from":"userA",
"localField":"name",
"foreignField":"username",
"as":"user"
}
},
{"$project":{
"_id":0
}
},
{
"$unwind": "$user"
},
{"$project":{
"user._id":0
}
}
])
db.report.insert([
{ "_id" : 1, "name" : "Dev" },
{ "_id" : 2, "name" : "Eliot", "reportsTo" : "Dev" },
{ "_id" : 3, "name" : "Ron", "reportsTo" : "Eliot" },
{ "_id" : 4, "name" : "Andrew", "reportsTo" : "Eliot" },
{ "_id" : 5, "name" : "Asya", "reportsTo" : "Ron" },
{ "_id" : 6, "name" : "Dan", "reportsTo" : "Andrew" }
])
//图查询
db.report.aggregate([{
"$graphLookup" : {
"from":"report",
"startWith":"$reportsTo",
"connectFromField":"reportsTo",
"connectToField":"name",
"as":"reportHierarchy",
"maxDepth":10
}
}])
db.mp3.insertMany([
{"val":1, "name":"A", "tar":"C"},
{"val":2, "name":"B", "tar":"D"},
{"val":3, "name":"C", "tar":"D"},
{"val":4, "name":"D", "tar":"B"}
])
db.mp.insertMany([
{"val":1, "name":"A", "tar":["B","C"]},
{"val":2, "name":"B", "tar":["D","E"]},
{"val":3, "name":"C", "tar":["E","F"]},
{"val":4, "name":"D", "tar":["F","A"]}
])
db.mp.insertOne({"val":1, "name":"A", "tar":["F","H"]})
db.src.insertMany([
{"uname":"A", "age":28, "addr":"shenzheng"},
{"uname":"B", "age":30, "addr":"hangzhou"}
])
//过滤,图查询,投影
db.src.aggregate([
{
"$match":{
"age":{
"$gte":20
},
"uname":{
"$exists":1
}
}
},{
"$graphLookup":{
"from":"mp",
"startWith":"$uname",
"connectFromField":"tar",
"connectToField":"name",
"as":"next",
"maxDepth":10
}
},
{
"$project":{
"_id":0,
"uname":1,
"next.name":1,
"next.tar":1
}
}
])
//选择,然后连接
db.src.aggregate([
{
"$match":{
"age":{
"$gte":20
},
"uname":{
"$exists":1
}
}
},
{
"$lookup":{
"from":"mp",
"localField":"uname",
"foreignField":"name",
"as":"next",
}
}
])
db.book.insertMany([
{"name":"A", "price":10, "count":10},
{"name":"B", "price":9, "count":12},
{"name":"C", "price":6, "count":7},
{"name":"D", "price":7, "count":9},
{"name":"E", "price":8, "count":10},
{"name":"F", "price":5, "count":20}
])
db.book.aggregate([
{
"$match":{
"$expr":{
"$gte":[
{"$multiply":["$price","$count"]},
100
]
}
}
}
])
db.u.insertMany([
{"FieldA":"a1", "FieldB":"b1", "FieldC":[{"w":0,"h":6},{"w":10,"h":19}]},
{"FieldA":"a2", "FieldB":"b2", "FieldC":[{"w":1,"h":5},{"w":11,"h":18}]},
{"FieldA":"a3", "FieldB":"b3", "FieldC":[{"w":2,"h":4},{"w":12,"h":17}]},
{"FieldA":"a4", "FieldB":"b4", "FieldC":[{"w":3,"h":3},{"w":13,"h":16}]},
{"FieldA":"a5", "FieldB":"b5", "FieldC":[{"w":4,"h":2},{"w":14,"h":15}]}
])
db.v.insertMany([
{"FieldA":"a1", "FieldD":1, "FieldE":20, "arr":[10,18,30]},
{"FieldA":"a2", "FieldD":2, "FieldE":21, "arr":[12,20,40]},
{"FieldA":"a3", "FieldD":3, "FieldE":22, "arr":[16,59,35]},
{"FieldA":"a4", "FieldD":4, "FieldE":23, "arr":[15,22,36]},
{"FieldA":"a5", "FieldD":6, "FieldE":24, "arr":[14,20,30]}
])
//二元操作 等于=查询
db.v.find({"FieldD":{"$eq":2}})
//使用用expr进行计算
db.v.find({"$expr":{
"$and":[
{"$gte":[{"$size":"$arr"},3]},
{"$lte":[{"$multiply":["$FieldD","$FieldE"]},60]},
{"$gte":[{"$sum":"$arr"},60]} //对数组求和
]
}})
//if then else 示例
db.v.find({"$expr":{
"$gte":[{"$cond":{
"if":{"$gte":["$FieldD",3]},
"then":{"$multiply":["$FieldE", 3]},
"else":{"$multiply":["$FieldE", 4]}
}},70]
}}).sort({"FieldD":-1})