- 聚合(aggregate)主要用於計算數據,類似sql中的sum(),avg()。
|
1
|
db.集合名稱.aggregate({管道:{表達式}})
|
管道
管道在Unix和Linux中一般用於將當前命令的輸出結果作為下一個命令的輸入 在mongodb中,管道具有同樣的作用,文檔處理完畢后,通過管道進行下一次處理 常用管道
$group:將集合中的文檔分組,可用於統計結果 $match:過濾數據,只輸出符合條件的文檔 $project:修改輸入文檔的結構,如重命名、增加、刪除字段、創建計算結果 $sort:將輸入文檔排序后輸出 $limit:限制聚合管道返回的文檔數 $skip:跳過指定數量的文檔,並返回余下的文檔 $unwind:將數組類型的字段進行拆分
表達式
處理輸入文檔並輸出
|
1
|
表達式:'$列名'
|
常用的表達式
$sum:計算總和 $avg:計算平均值 $min:獲取最小值 $max:獲取最大值 $push:在結果文檔中插入值到一個數組中 $first:根據資源文檔的排序獲取第一個文檔數據 $last:根據資源文檔的排序獲取最后一個文檔數據
$group
將集合中的文檔分組,可用於統計結果
_id表示分組的依據,使用某個字段的格式為’$字段’
例1:統計男生、女生的總人數
|
1
2
3
4
5
6
|
db.stu.aggregate({
$group:{
_id:'$gender',
con:{$sum:1}
}
})
|

group by null:將集合中所有文檔分為一組
例2:求學生總數和平均年齡
|
1
2
3
4
5
6
7
8
|
db.stu.aggregate(
{$group:{
_id:null,
coun:{$sum:1},
avgAge:{$avg:'$age'}
}
}
)
|

透視數據
|
1
2
3
4
5
6
7
8
|
// 統計學生性別以及學生的姓名
db.stu.aggregate(
{$group:{
_id:'$gender',
name:{$push:'$name'}
}
}
)
|

使用$$ROOT可以將文檔內容加入到結果集的數組中
|
1
2
3
4
5
6
7
|
db.stu.aggregate(
{$group:{
_id:'$gender',
name:{$push:'$$ROOT'}
}
}
)
|

$match
用於過濾數據,只輸出符合條件的文檔
例子
|
1
2
3
4
5
|
// 查詢年齡大於20的男生、女生人數
db.stu.aggregate(
{$match:{age:{$gt:20}}},
{$group:{_id:'$gender',con:{$sum:1}}}
)
|

$project
修改輸入文檔的結構,如重命名、增加、刪除字段、創建計算結果
例子
|
1
2
3
4
5
|
// 查詢男生、女生人數,輸出人數
db.stu.aggregate(
{$group:{_id:'$gender',counter:{$sum:1}}},
{$project:{_id:0,counter:1}}
)
|

$sort
將輸入的文檔排序之后輸出
例1:查詢學生信息,按年齡升序
|
1
2
3
|
db.stu.aggregate(
{$sort:{age:1}}
)
|

例2:查詢男生、女生人數,按人數降序
|
1
2
3
4
|
db.stu.aggregate(
{$group:{_id:'$gender',coun:{$sum:1}}},
{$sort:{coun:-1}}
)
|

$limit
限制聚合管道返回的文檔數
|
1
2
3
4
|
// 查詢兩個學生的信息
db.stu.aggregate(
{$limit:2}
)
|

$skip
跳過指定的數量的文檔,並返回余下的文檔
|
1
2
3
4
|
// 查詢第三條開始的學生的信息
db.stu.aggregate(
{$skip:2}
)
|

$limit和$skip一起使用
|
1
2
3
4
5
6
7
|
// 統計男生、女生人數,按人數升序,取第二條數據
db.stu.aggregate(
{$group:{_id:'$gender',coun:{$sum:1}}},
{$sort:{coun:1}},
{$skip:1},
{$limit:1}
)
|

$unwind
將文檔中的某一個數組類型字段拆分成多條,每條包含數組中的一個值
語法1:
對某字段值進行拆分
|
1
|
db.集合名稱.aggregate({$unwind:'$字段名稱'})
|
准備數據:
|
1
|
db.t2.insert({_id:1,item:'t-shirt',size:['S','M','L']})
|
查詢
|
1
|
db.t2.aggregate({$unwind:'$size'})
|

語法2:
對某字段值進行拆分 處理空數組、非數組、無字段、null情況 屬性preserveNullAndEmptyArrays值為false表示丟棄屬性值為空的文檔 屬性preserveNullAndEmptyArrays值為true表示保留屬性值為空的文檔
|
1
2
3
4
5
6
|
db.inventory.aggregate({
$unwind:{
path:'$字段名稱',
preserveNullAndEmptyArrays:<boolean> #防止數據丟失
}
})</boolean>
|
構造數據
|
1
2
3
4
5
6
7
|
db.t3.insert([
{ "_id" : 1, "item" : "a", "size": [ "S", "M", "L"] },
{ "_id" : 2, "item" : "b", "size" : [ ] },
{ "_id" : 3, "item" : "c", "size": "M" },
{ "_id" : 4, "item" : "d" },
{ "_id" : 5, "item" : "e", "size" : null }
])
|
1 db.product.aggregate([
2 {
3 $lookup:
4 {
5 from: "orders",//關聯的表
6 localField: "_id",//關聯id
7 foreignField: "pid",//from表的關聯字段
8 as: "inventory_docs"//輸出結果
9 }
10 }
11 ])
java代碼演示:
public class mongotest {
private final static Logger log = Logger.getLogger(mongotest.class);
public static void main(String[] args) throws UnknownHostException {
log.info( ":start");
MongoClient client = new MongoClient("127.0.0.1", 27017);
DB product1 = client.getDB("duobiao");
client.getDatabaseNames();
DBCollection product = product1.getCollection("product");
// Bson lookup = lookup("orders", "_id", "pid", "inventory_docs");
BasicDBObject basicDBObject= new BasicDBObject();
basicDBObject.put("from","orders");
basicDBObject.put("localField","_id");
basicDBObject.put("foreignField","pid");
basicDBObject.put("as","inventory_docs");
DBObject match = new BasicDBObject("$lookup",basicDBObject);
AggregationOutput aggregate = product.aggregate(match);
Iterable<DBObject> list= aggregate.results();
for(DBObject dbObject:list){
System.out.println(dbObject.get("_id") + " " + dbObject.get("price"));
}
}
}
