MongoDB聚合


聚合操作處理資料記錄並返回計算結果。 聚合操作將多個文件中的值組合在一起,並可對分組資料執行各種操作,以返回單個結果。 在SQL中的 count(*)group by組合相當於mongodb 中的聚合功能。

aggregate()方法

對於MongoDB中的聚合,應該使用aggregate()方法。

語法

aggregate()方法的基本語法如下 -

>db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)

範例

假設在集合中,有以下資料 -

db.article.insert([
{
   _id: 100,
   title: 'MongoDB Overview',
   description: 'MongoDB is no sql database',
   by_user: 'Maxsu',
   url: 'https://www.tw511.com',
   tags: ['mongodb', 'database', 'NoSQL'],
   likes: 100
},
{
   _id: 101,
   title: 'NoSQL Overview', 
   description: 'No sql database is very fast',
   by_user: 'Maxsu',
   url: 'https://www.tw511.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: '/18/142/4124.html',
   tags: ['MySQL', 'database', 'SQL'],
   likes: 350
}])

現在從上面的集合中,如果要顯示一個列表,說明每個使用者寫入了多少個教學,那麼可使用以下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分組了文件,並且每次發生的by_user的前一個值的值都被遞增。以下是可用聚合表示式的列表。

表示式 描述 範例
$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 從集合中的所有文件獲取相應值的最小值。 db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$min : "$likes"}}}])
$max 從集合中的所有文件獲取相應值的最大值。 db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$max : "$likes"}}}])
$push 將值插入到生成的文件中的陣列中。 db.mycol.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}])
$addToSet 將值插入生成的文件中的陣列,但不會建立重複項。 db.mycol.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}])
$first 根據分組從源文件獲取第一個文件。 通常情況下,這只適用於以前應用的「$sort」階段。 db.mycol.aggregate([{$group : {_id : "$by_user", first_url : {$first : "$url"}}}])
$last 根據分組從源文件獲取最後一個文件。通常情況下,這只適用於以前應用的「$sort」階段。 db.mycol.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}])

管道概念

在UNIX命令中,shell管道可以對某些輸入執行操作,並將輸出用作下一個命令的輸入。 MongoDB也在聚合框架中支援類似的概念。每一組輸出可作為另一組文件的輸入,並生成一組生成的文件(或最終生成的JSON文件在管道的末尾)。這樣就可以再次用於下一階段等等。

以下是在聚合框架可能的階段 -

  • $project - 用於從集合中選擇一些特定欄位。
  • $match - 這是一個過濾操作,因此可以減少作為下一階段輸入的文件數量。
  • $group - 這是上面討論的實際聚合。
  • $sort - 排序文件。
  • $skip - 通過這種方式,可以在給定數量的文件的文件列表中向前跳過。
  • $limit - 限制從當前位置開始的給定數量的文件數量。
  • $unwind - 用於展開正在使用陣列的文件。使用陣列時,資料是預先加入的,此操作將被復原,以便再次單獨使用文件。 因此,在這個階段,將增加下一階段的檔案數量。