基本用法
db.collection.aggregate( [ { <stage> }, ... ] )
stage如下
| 名稱 | 描述 |
| $addFields | 將新的字段添加到文檔中,輸出的文檔包含已經存在的字段和新加入的字段 |
| $bucket | 根據指定的表達式和存儲區邊界將傳入文檔分組到稱為buckets的組中。 |
| $bucketAuto | 根據指定的表達式將傳入文檔分類到特定數量的組(稱為buckets)。存儲區邊界自動確定,試圖將文檔均勻分布到指定數量的buckets中。 |
| $collStats | 返回有關集合或視圖的統計信息。 |
| $count | 返回聚合管道的計數 |
| $currentOp | 返回有關MongoDB部署的活動和/或休眠操作的信息 |
| $facet | 在同一組輸入文檔中的單個階段內處理多個聚合流水線。支持創建多方面的聚合,能夠在單個階段中跨多個維度或方面表征數據。 |
| $geoNear | 根據地理空間點的接近度返回有序的文檔流。包含地理空間數據的$ match,$ sort和$ limit功能。輸出文件包含一個額外的距離字段,並可包含位置標識符字段。 |
| $graphLookup | 對集合執行遞歸搜索。為每個輸出文檔添加一個新的數組字段,其中包含該文檔的遞歸搜索的遍歷結果 |
| $group | 按指定的標識符表達式輸入文檔,並將累加器表達式(如果指定)應用於每個組。消耗所有輸入文檔並為每個不同的組輸出一個文檔。輸出文件只包含標識符字段,如果指定了,則包含累積字段。 |
| $indexStats | 返回有關使用集合中每個索引的統計信息。 |
| $limit | 將未修改的前n個文檔傳遞到管道,其中n是指定的限制。對於每個輸入文檔,輸出一個文檔(前n個文檔)或零文檔(前n個文檔之后)。 |
| $listLocalSessions | 列出最近在當前連接的mongos或mongod實例中使用的所有活動會話。這些會話可能尚未傳播到system.sessions集合。 |
| $listSessions | 列出所有活動時間足以傳播到system.sessions集合的所有會話。 |
| $lookup | 將左外連接執行到同一數據庫中的另一個集合,以過濾“已連接”集合中的文檔進行處理。 |
| $match | 過濾文檔流,只允許匹配的文檔未經修改地傳遞到下一個管道階段。 $ match使用標准的MongoDB查詢。對於每個輸入文檔,輸出一個文檔(匹配)或零個文檔(不匹配)。 |
| $out | 將聚合管道的結果文檔寫入集合。要使用$ out階段,它必須是管道中的最后一個階段。 |
| $project | 重新設計流中的每個文檔,例如添加新字段或刪除現有字段。對於每個輸入文檔,輸出一個文檔。 |
| $redact | 根據存儲在文檔本身中的信息限制每個文檔的內容,重新整形流中的每個文檔。包含$ project和$ match的功能。可用於實施字段級別的編校。對於每個輸入文檔,輸出一個或零個文檔。 |
| $replaceRoot | 用指定的嵌入式文檔替換文檔。該操作將替換輸入文檔中的所有現有字段,包括_id字段。指定嵌入在輸入文檔中的文檔以將嵌入式文檔提升到頂層。 |
| $sample | 從其輸入中隨機選擇指定數量的文檔。 |
| $skip | 跳過前n個文檔,其中n是指定的跳過編號,並將未修改的其余文檔傳遞到管道。對於每個輸入文檔,輸出零文檔(對於前n個文檔)或一個文檔(如果在前n個文檔之后)。 |
| $sort | 通過指定的排序鍵對文檔流進行重新排序。只有訂單改變了;文件保持不變。對於每個輸入文檔,輸出一個文檔。 |
| $sortByCount | 根據指定表達式的值對傳入文檔分組,然后計算每個不同組中文檔的數量。 |
| $unwind | 從輸入文檔解構數組字段以輸出每個元素的文檔。每個輸出文檔用一個元素值替換數組。對於每個輸入文檔,輸出n個文檔,其中n是數組元素的數量,對於空數組可以為零。 |
以上翻譯自谷歌翻譯
常用的stage有
$count
經常搭配其他的stage一起使用
樣例
假設數據如下
{ "_id" : 1, "subject" : "History", "score" : 88 }
{ "_id" : 2, "subject" : "History", "score" : 92 }
{ "_id" : 3, "subject" : "History", "score" : 97 }
{ "_id" : 4, "subject" : "History", "score" : 71 }
{ "_id" : 5, "subject" : "History", "score" : 79 }
{ "_id" : 6, "subject" : "History", "score" : 83 }
使用以下聚合操作
db.scores.aggregate( [ { $match: { score: { $gt: 80 } } }, { $count: "passing_scores" } ] )
意思是匹配score字段大於80分的文檔,然后計算數量,重命名為passing_scores輸出
輸出如下
{ "passing_scores" : 4 }
$group
用法如下
{ $group: { _id: <expression>, <field1>: { <accumulator1> : <expression1> }, ... } }
<accumulator>操作如下
$sum,$avg,$first,$last,$max,$min,$push,$addToSet,$stdDevPop,$stdDevSamp
用途就跟名稱差不多
樣例
{ "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2, "date" : ISODate("2014-03-01T08:00:00Z") }
{ "_id" : 2, "item" : "jkl", "price" : 20, "quantity" : 1, "date" : ISODate("2014-03-01T09:00:00Z") }
{ "_id" : 3, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-03-15T09:00:00Z") }
{ "_id" : 4, "item" : "xyz", "price" : 5, "quantity" : 20, "date" : ISODate("2014-04-04T11:21:39.736Z") }
{ "_id" : 5, "item" : "abc", "price" : 10, "quantity" : 10, "date" : ISODate("2014-04-04T21:23:13.331Z") }
使用以下聚合操作
db.sales.aggregate( [ { $group : { _id : { month: { $month: "$date" }, day: { $dayOfMonth: "$date" }, year: { $year: "$date" } }, totalPrice: { $sum: { $multiply: [ "$price", "$quantity" ] } }, averageQuantity: { $avg: "$quantity" }, count: { $sum: 1 } } } ] )
意思是將文檔根據時間(相同的年月日)分組,並計算其總價格(價格*數量求和),平均的數量,每個分組有多少個文檔
結果如下
{ "_id" : { "month" : 3, "day" : 15, "year" : 2014 }, "totalPrice" : 50, "averageQuantity" : 10, "count" : 1 }
{ "_id" : { "month" : 4, "day" : 4, "year" : 2014 }, "totalPrice" : 200, "averageQuantity" : 15, "count" : 2 }
{ "_id" : { "month" : 3, "day" : 1, "year" : 2014 }, "totalPrice" : 40, "averageQuantity" : 1.5, "count" : 2 }
使用以下聚合操作
db.sales.aggregate( [ { $group : { _id : null, totalPrice: { $sum: { $multiply: [ "$price", "$quantity" ] } }, averageQuantity: { $avg: "$quantity" }, count: { $sum: 1 } } } ] )
結果如下
{ "_id" : null, "totalPrice" : 290, "averageQuantity" : 8.6, "count" : 5 }
更多操作見https://docs.mongodb.com/manual/reference/operator/aggregation/group/#pipe._S_group
$limit
用法如下
db.article.aggregate( { $limit : 5 } );
意思就是現在article只返回前5個文檔
$lookup
用法如下
{ $lookup: { from: <collection to join>, localField: <field from the input documents>, foreignField: <field from the documents of the "from" collection>, as: <output array field> } }
from表示另一個要連接的表b,localField表示該表a中用於和表b連接的字段,foreignField表示表b中用於和表a連接的字段,as表示為輸出結果命名
SELECT *, <output array field> FROM collection WHERE <output array field> IN (SELECT * FROM <collection to join> WHERE <foreignField>= <collection.localField>);
相當於以上的sql語句
另一種用法
{ $lookup: { from: <collection to join>, let: { <var_1>: <expression>, …, <var_n>: <expression> }, pipeline: [ <pipeline to execute on the collection to join> ], as: <output array field> } }
對應的sql語句
SELECT *, <output array field> FROM collection WHERE <output array field> IN (SELECT <documents as determined from the pipeline> FROM <collection to join> WHERE <pipeline> );
樣例
插入如下數據
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" } } ])
返回結果如下
{ "_id" : 1, "item" : "almonds", "price" : 12, "quantity" : 2, "inventory_docs" : [ { "_id" : 1, "sku" : "almonds", "description" : "product 1", "instock" : 120 } ] } { "_id" : 2, "item" : "pecans", "price" : 20, "quantity" : 1, "inventory_docs" : [ { "_id" : 4, "sku" : "pecans", "description" : "product 4", "instock" : 70 } ] } { "_id" : 3, "inventory_docs" : [ { "_id" : 5, "sku" : null, "description" : "Incomplete" }, { "_id" : 6 } ] }
相同sql語句如下
SELECT *, inventory_docs FROM orders WHERE inventory_docs IN (SELECT * FROM inventory WHERE sku= orders.item);
更多內容見https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/#pipe._S_lookup
$match
用法如下
{ $match: { <query> } }
樣例
數據如下
{ "_id" : ObjectId("512bc95fe835e68f199c8686"), "author" : "dave", "score" : 80, "views" : 100 }
{ "_id" : ObjectId("512bc962e835e68f199c8687"), "author" : "dave", "score" : 85, "views" : 521 }
{ "_id" : ObjectId("55f5a192d4bede9ac365b257"), "author" : "ahn", "score" : 60, "views" : 1000 }
{ "_id" : ObjectId("55f5a192d4bede9ac365b258"), "author" : "li", "score" : 55, "views" : 5000 }
{ "_id" : ObjectId("55f5a1d3d4bede9ac365b259"), "author" : "annT", "score" : 60, "views" : 50 }
{ "_id" : ObjectId("55f5a1d3d4bede9ac365b25a"), "author" : "li", "score" : 94, "views" : 999 }
{ "_id" : ObjectId("55f5a1d3d4bede9ac365b25b"), "author" : "ty", "score" : 95, "views" : 1000 }
聚合操作如下
db.articles.aggregate( [ { $match : { author : "dave" } } ] );
結果如下
{ "_id" : ObjectId("512bc95fe835e68f199c8686"), "author" : "dave", "score" : 80, "views" : 100 }
{ "_id" : ObjectId("512bc962e835e68f199c8687"), "author" : "dave", "score" : 85, "views" : 521 }
$out
用法如下
{ $out: "<output-collection>" }
樣例
數據如下
{ "_id" : 8751, "title" : "The Banquet", "author" : "Dante", "copies" : 2 }
{ "_id" : 8752, "title" : "Divine Comedy", "author" : "Dante", "copies" : 1 }
{ "_id" : 8645, "title" : "Eclogues", "author" : "Dante", "copies" : 2 }
{ "_id" : 7000, "title" : "The Odyssey", "author" : "Homer", "copies" : 10 }
{ "_id" : 7020, "title" : "Iliad", "author" : "Homer", "copies" : 10 }
聚合操作如下
db.books.aggregate( [ { $group : { _id : "$author", books: { $push: "$title" } } }, { $out : "authors" } ] )
意思是將books的author字段分類並作為_id字段的內容,將相同作者的title都push到books字段中,將其插入authors表中
結果如下
{ "_id" : "Homer", "books" : [ "The Odyssey", "Iliad" ] }
{ "_id" : "Dante", "books" : [ "The Banquet", "Divine Comedy", "Eclogues" ] }
$project
用法如下
{ $project: { <specification(s)> } }
樣例
數據如下
{ "_id" : 1, title: "abc123", isbn: "0001122223334", author: { last: "zzz", first: "aaa" }, copies: 5 }
聚合操作如下
db.books.aggregate( [ { $project : { title : 1 , author : 1 } } ] )
結果如下
{ "_id" : 1, "title" : "abc123", "author" : { "last" : "zzz", "first" : "aaa" } }
更多內容見https://docs.mongodb.com/manual/reference/operator/aggregation/project/#pipe._S_project
$skip
用法如下
{ $skip: <positive integer> }
樣例
db.article.aggregate( { $skip : 5 } );
意思也很簡單就是跳過前5個文檔
$sort
用法如下
{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } }
樣例
db.users.aggregate( [ { $sort : { age : -1, posts: 1 } } ] )
-1表示降序排列,1表示升序排列
$sortByCont
用法見https://docs.mongodb.com/manual/reference/operator/aggregation/sortByCount/#pipe._S_sortByCount
$unwind
用法見https://docs.mongodb.com/manual/reference/operator/aggregation/unwind/#pipe._S_unwind
