iT邦幫忙

2022 iThome 鐵人賽

DAY 13
0
自我挑戰組

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

被MongoDB用Aggregate暴打的後端小菜雞日記-day13-$bucket 桶子分組

  • 分享至 

  • xImage
  •  

今天要來介紹aggregate比較進階的用法$bucket,這個操作符它的用法很類似$group,都是可以將資料透過特定欄位進行分組。

不同的地方在於$group會把欄位相同值的資料當成一組,但是$bucket可以指定特定範圍值的資料為一組。

假設我們現在有學生的成績資料

  { id: 1, name: "小美", math: 20 },
  { id: 2, name: "小王", math: 86 },
  { id: 3, name: "小明", math: 98 },
  { id: 4, name: "小帥", math: 56 },
  { id: 5, name: "小真", math: 12 },
  { id: 6, name: "大明", math: "缺考" }

老師想要按照數學成績幫學生分組,並且知道每一組的學生有幾人、名字是誰,我們可以用以下指令,將學生分成3組,1~40分、40~70分、70~100分。

student.aggregate([
  {
    $bucket: {
      groupBy: "$math", // 分組的欄位
      boundaries: [1, 40, 70, 101], // 分組的區間範圍
      default: "other", // 如果沒有在上面的範圍內,則會在other這一組
      output: {
        // 決定分組後,要回傳的欄位(每一組都會這樣計算)
        "count": { $sum: 1 },
        "student": {
          $push: {
            "student": "$name"
          }
        }
      }
    }
  }
]);

其中boundaries可以決定分組的區間,按照[1, 40, 70, 101]的寫法,會是分成1≤math<4040≤math<7070≤math<101這三組,為了將100分的學生也包含在內,所以最後一個才寫101。

另外default可以讓數學不在1~100分這個範圍內的資料,或原本資料本身缺少math這個欄位,都會被歸類在other這一組。

若是使用boundaries: [0, 40, 70, 101]這種分法,原本資料本身缺少math這個欄位,會被歸類在0~40分這一組,應該是因為mongodb在判斷上,認為0、null、false都是falsy value的一種。

最後回傳的資料會是

  { _id: 1, count: 2, student: [{ name: "小美" }, { name: "小真" }] },
  { _id: 40, count: 1, student: [{ name: "小帥" }] },
  { _id: 70, count: 2, student: [{ name: "小王" }, { name: "小明" }] },
  { _id: "other", count: 1, student: [{ name: "大明" }] }

ps.分組後的_id值會是分組值得下限值當id。

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


上一篇
被MongoDB用Aggregate暴打的後端小菜雞日記-day12-$cond、$switch條件判斷
下一篇
被MongoDB用Aggregate暴打的後端小菜雞日記-day14-$facet 一次使用多個pipeline
系列文
被MongoDB用Aggregate暴打的後端小菜雞日記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言