- 聚合(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")); } } }