聚合操作處理數(shù)據(jù)記錄并返回計算結(jié)果。 聚合操作將多個文檔中的值組合在一起,并可對分組數(shù)據(jù)執(zhí)行各種操作,以返回單個結(jié)果。 在SQL中的 count(*)與group by組合相當(dāng)于mongodb 中的聚合功能。
對于MongoDB中的聚合,應(yīng)該使用aggregate()方法。
語法
aggregate()方法的基本語法如下 -
>db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)
示例
假設(shè)在集合中,有以下數(shù)據(jù) -
db.article.insert([
{
_id: 100,
title: 'MongoDB Overview',
description: 'MongoDB is no sql database',
by_user: 'Maxsu',
url: 'http://www.yiibai.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 100
},
{
_id: 101,
title: 'NoSQL Overview',
description: 'No sql database is very fast',
by_user: 'Maxsu',
url: 'http://www.yiibai.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 10
},
{
_id: 102,
title: 'Neo4j Overview',
description: 'Neo4j is no sql database',
by_user: 'Kuber',
url: 'http://www.neo4j.com',
tags: ['neo4j', 'database', 'NoSQL'],
likes: 750
},
{
_id: 103,
title: 'MySQL Overview',
description: 'MySQL is sql database',
by_user: 'Curry',
url: 'http://www.yiibai.com/mysql/',
tags: ['MySQL', 'database', 'SQL'],
likes: 350
}])
現(xiàn)在從上面的集合中,如果要顯示一個列表,說明每個用戶寫入了多少個教程,那么可使用以下aggregate()方法 -
> db.article.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}])
{ "_id" : "Curry", "num_tutorial" : 1 }
{ "_id" : "Kuber", "num_tutorial" : 1 }
{ "_id" : "Maxsu", "num_tutorial" : 2 }
>
對于上述用例的Sql等效查詢是:
select by_user, count(*) as num_tutorial from `article` group by by_user;
在上面的例子中,我們按字段by_user分組了文檔,并且每次發(fā)生的by_user的前一個值的值都被遞增。以下是可用聚合表達(dá)式的列表。
| 表達(dá)式 | 描述 | 示例 |
|---|---|---|
$sum |
從集合中的所有文檔中求出定義的值。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : "$likes"}}}]) |
$avg |
計算集合中所有文檔的所有給定值的平均值。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$avg : "$likes"}}}]) |
$min |
從集合中的所有文檔獲取相應(yīng)值的最小值。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$min : "$likes"}}}]) |
$max |
從集合中的所有文檔獲取相應(yīng)值的最大值。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$max : "$likes"}}}]) |
$push |
將值插入到生成的文檔中的數(shù)組中。 | db.mycol.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}]) |
$addToSet |
將值插入生成的文檔中的數(shù)組,但不會創(chuàng)建重復(fù)項。 | db.mycol.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}]) |
$first |
根據(jù)分組從源文檔獲取第一個文檔。 通常情況下,這只適用于以前應(yīng)用的“$sort”階段。 |
db.mycol.aggregate([{$group : {_id : "$by_user", first_url : {$first : "$url"}}}]) |
$last |
根據(jù)分組從源文檔獲取最后一個文檔。通常情況下,這只適用于以前應(yīng)用的“$sort”階段。 |
db.mycol.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}]) |
在UNIX命令中,shell管道可以對某些輸入執(zhí)行操作,并將輸出用作下一個命令的輸入。 MongoDB也在聚合框架中支持類似的概念。每一組輸出可作為另一組文檔的輸入,并生成一組生成的文檔(或最終生成的JSON文檔在管道的末尾)。這樣就可以再次用于下一階段等等。
以下是在聚合框架可能的階段 -
$project - 用于從集合中選擇一些特定字段。$match - 這是一個過濾操作,因此可以減少作為下一階段輸入的文檔數(shù)量。$group - 這是上面討論的實際聚合。$sort - 排序文檔。$skip - 通過這種方式,可以在給定數(shù)量的文檔的文檔列表中向前跳過。$limit - 限制從當(dāng)前位置開始的給定數(shù)量的文檔數(shù)量。$unwind - 用于展開正在使用數(shù)組的文檔。使用數(shù)組時,數(shù)據(jù)是預(yù)先加入的,此操作將被撤銷,以便再次單獨使用文檔。 因此,在這個階段,將增加下一階段的文件數(shù)量。