iT邦幫忙

2022 iThome 鐵人賽

DAY 7
0
自我挑戰組

被MongoDB用Aggregate暴打的後端小菜雞日記系列 第 7

被MongoDB用Aggregate暴打的後端小菜雞日記-day7-用$group將資料分組(上)

  • 分享至 

  • xImage
  •  

今天我們要介紹$group,它可以將資料進行分組,同時進行特定的運算,回傳運算後的結果。

例如:現在有每位學生三次段考的成績,老師需要針對這些成績進行計算。

  { _id: 1, student: 1, test: 1, math: 20, english: 45 },
  { _id: 2, student: 1, test: 2, math: 70, english: 78 },
  { _id: 3, student: 2, test: 1, math: 30, english: 80 },
  { _id: 4, student: 2, test: 2, math: 98, english: 100 },
  { _id: 5, student: 3, test: 1, math: 85, english: 83 },
  { _id: 6, student: 3, test: 2, math: 94, english: 70 }

情境一:我們想找出每一次段考數學最高分,和英文最低分的分數。

score.aggregate([
  {
    $group: {
      _id: "$test", // 用來分組的欄位
      maxMath: { $max: "$math" },  // 取math欄位的最大值
      minEnglish: { $min: "$english" }  // 取english的最小值
    }
  }
]);

最後會得到以下資料

{ _id: 1, maxMath: 85, minEnglish: 45 },
{ _id: 2, maxMath: 98, minEnglish: 70 }

在使用$group必須注意,回傳資料裡面的_id不會是原本的id值了,而是test這個欄位數值,以及原本的欄位資料,如果沒有特別用指令寫在新增的欄位裡面,基本上會在這一次的pipeline消失,不會往下傳給下一個aggregate pipeline。

情境二:我們想找出每一次段考數學第一、第二高分,可以使用$maxN取前面最高的幾筆資料。

score.aggregate([
  {
    $group: {
      _id: "$test",
      maxMath: {
        $maxN: {
          input: "$math", // 要找最大值的欄位
          n: 2  // 要取幾筆資料
        }
      }
    }
  }
]);

最後回傳

{ _id: 1, maxMath: [85, 30] },
{ _id: 2, maxMath: [98, 94] }

ps.$maxN需要mongodb版本在5.2.以上才能使用。

情境三:計算每一次段考數學和英文的平均分數,可以使用$avg來計算欄位的平均值。

score.aggregate([
  {
    $group: {
      _id: "$test",
      mathAvg: { $avg: "$math" },
      englishAvg: { $avg: "$english" }
    }
  }
]);

最後回傳 (ps.事實上我用mongodb跑過,可以算到小數第15位,只是被我省略)

{ _id: 1, mathAvg: 45, englishAvg: 69.3 },
{ _id: 2, mathAvg: 87.3, englishAvg: 82.6 }

情境四:計算每一次段考數學標準差。
標準差的算法,官方有提供兩種操作符,$stdDevSamp$stdDevPop,詳細差異請參考官方文件。

score.aggregate([
  {
    $group: {
      _id: "$test",
      mathStdDevSamp: { $stdDevSamp: "$math" },
      mathStdDevPop: { $stdDevPop: "$math" }
    }
  }
]);

得到的結果,可以自己感受一下差異?

{ _id: 1, mathStdDevSamp: 35, mathStdDevPop: 28.577380332470412 },
{ _id: 2, mathStdDevSamp: 15.143755588800731, mathStdDevPop: 12.36482466066094 }

本篇文章同步放在我的部落格,大家有空可以進來逛逛


上一篇
被MongoDB用Aggregate暴打的後端小菜雞日記-day6-用$project新增欄位
下一篇
被MongoDB用Aggregate暴打的後端小菜雞日記-day8-用$group將資料分組(下)
系列文
被MongoDB用Aggregate暴打的後端小菜雞日記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言