iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 20
0
AI & Data

從入門到精通 MongoDB系列 第 25

Day25: 聚合(Aggregation)操作(1) - Aggregation pipeline

我們接著要開始介紹 MongoDB 中最重要的概念:聚合 Aggregation

這篇文章我們會先介紹 MongoDB 執行聚合操作的方法:聚合管線(Aggregation Pipeline)


Aggregation Pipeline

聚合管線 Aggregation Pipeline 是透過 Aggregation framework 將 document 進入一個由多個階段(stage)組成的管線,可以對每個階段的管線進行分組、過濾等功能,在經過一系列的處理之後,輸出相應的聚合結果。

以下是這篇文章會使用到的範例資料 orders.json:

[
    {
        "name": "Jack",
        "amount": 500,
        "status": "finished"
    },
    {
        "name": "Jack",
        "amount": 250,
        "status": "finished"
    },
    {
        "name": "Mark",
        "amount": 200,
        "status": "finished"
    },
    {
        "name": "Mark",
        "amount": 300,
        "status": "waiting"
    }
]

例如我們想要對這筆資料進行以下的操作:

  1. 過濾(match)出狀態為 finished 的訂單
  2. 再把訂單依照姓名來分組
  3. 對分組後的資料依照姓名進行聚合(統計每個人的訂單總金額)

以上三個步驟是一步接著一步的,因此整個流程是一個 pipeline 操作(match, group, aggregation)


Aggregation Pipeline 的範例

我們先來查看 orders.json 這個檔案:db.orders.find()

接著我們使用以下的聚合管線程式來執行上面提到的範例操作:

db.orders.aggregate(
    [
        {$match:{status:"finished"}},
        {$group: {_id: "$name", total:{$sum: "$amount"}}},
        {$sort: {total:-1}}
    ]
)

當我們執行這個 pipeline 時,會將第一個步驟 $match 的結果傳給第二個步驟進行 $group,再將第二個步驟的結果傳給第三個步驟進行 $sort。

為了更好理解,我們將這三個步驟拆開來看:

步驟一、對 status 欄位進行過濾:

指令:db.orders.aggregate([{$match: {status: "finished"}}])

我們可以對這個結果進行排序:db.orders.aggregate([{$match: {status: "finished"}}, {$sort: {amount: 1}}])

  • 這個方法和使用 find().sort() 一樣:db.orders.find({status: "finished"}).sort({amount: 1})

步驟二、將過濾後的資料進行分組:

  • 使用 $group 對資料進行分組:db.orders.aggregate([{$match: {status: "finished"}}, {$group: {_id: "$name"}}])
  • 依照 name 欄位進行分組,並加各組內的 amount 欄位的值加總:db.orders.aggregate([{$match: {status: "finished"}}, {$group: {_id: "$name", total: {$sum: "$amount"}}}])

步驟三、將分組加總後的資料,依照 total 欄位進行排序:

  • db.orders.aggregate([{$match: {status: "finished"}}, {$group: {_id: "$name", total: {$sum: "$amount"}}}, {$sort: {total: 1}}])

Aggregation Pipeline 的練習

練習一:對 movie.json 中的所有導演求各自的票房總和

使用以下的 pipeline:

db.movie.aggregate(
    [
        {$group: {_id: "$director_name", total:{$sum: "$gross"}}},
        {$sort: {total:-1}}
    ]
)

練習二:對所有導演的 RMDB 平均分數排名

使用以下 pipeline:

db.movie.aggregate(
    [
        {$group: {_id: "$director_name", avg_imdb:{$avg: "$imdb_score"}}},
        {$sort: {avg_imdb:-1}}
    ]
)


今天介紹了 MongoDB 中最重要的概念:聚合 Aggregation,以及操作聚合的方法:聚合管線 Aggregation Pipeline,下一篇會接著介紹 $project 這個運算子的使用方法。


上一篇
Day24: MongoDB 中的地理空間資料處理
下一篇
Day26: 聚合(Aggregation)操作(2) - $project 及 $bucket
系列文
從入門到精通 MongoDB26

尚未有邦友留言

立即登入留言