iT邦幫忙

2022 iThome 鐵人賽

DAY 12
0
自我挑戰組

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

被MongoDB用Aggregate暴打的後端小菜雞日記-day12-$cond、$switch條件判斷

  • 分享至 

  • xImage
  •  

相信大家在寫程式碼的時候,一定都會用到if/else根據不同的條件,執行不同的程式碼,有時候如果條件多一點的話,還會使用switch。

但你能相信在MongoDB資料庫的搜尋語法也使用if/else,至少剛開始接觸aggregate的我是不相信拉,直到某一次為了一個需求,我用$bucket$facet寫了一段很長的pipeline程式碼,還無法達到我想要的結果,向主管求助才發現有這麼好用的語法。

首先我們先介紹$cond這個操作符,它跟我們熟悉的if/else用法很類似,寫法有兩種格式。

// 寫法一
$cond: { 
  if: <boolean-expression>,
  then: <true-case>,
  else: <false-case> 
}

// 寫法二
$cond: [ <boolean-expression>, <true-case>, <false-case> ]

其中<boolean-expression>代表判斷的條件,會根據這裡的結果是true或false決定要回傳的值是<true-case>還是<false-case>

例如:商店的會員等級制度是,每年消費一定要滿3000元,才是高級會員,否則是一般會員。
原本的會員資料如下

  { id: 1, name: "小美", age: 13, sex: 1, consume: 4300 },
  { id: 2, name: "小王", age: 34, sex: 0, consume: 1400 },
  { id: 3, name: "小明", age: 25, sex: 0, consume: 0 }

此時我們可以透過以下指令來判斷,每一個人的會員等級

customer.aggregate([
  {
    $addFields: {
      level: {
        $cond: {
          if: { $gte: ["$consume", 3000] },
          then: "高級會員",
          else: "一般會員"
        }
      }
    }
  },
  { $project: { name: 1, level: 1 } }
]);

// 回傳的資料
  { id: 1, name: "小美", level: "高級會員" },
  { id: 2, name: "小王", level: "一般會員" },
  { id: 3, name: "小明", level: "一般會員" }

或是用以下寫法,也會得到相同的資料

customer.aggregate([
  {
    $addFields: {
      level: {
        $cond: [{ $gte: ["$consume", 3000] }, "高級會員", "一般會員"]
      }
    }
  },
  { $project: { name: 1, level: 1 } }
]);

個人比較偏好第一種寫法,雖然在寫法上第二種方法比較簡潔,但是在閱讀上第一種方式比較好懂,尤其是對從來沒有接觸過$cond這個操作符的人,也能大概猜出這段程式碼在做什麼。


第二個要介紹的操作符是$switch,它可以根據不同條件,回傳不同的值。
例如:現在商店的會員等級制度,區分成只要註冊就是一般會員,每年消費1000元以上就是高級會員,消費3000元以上是VIP會員。

此時我們可以透過以下指令來判斷,每一個人的會員等級

customer.aggregate([
  {
    $addFields: {
      level: {
        $switch: {
          branches: [  // branches裡面可以寫很多條件
            // case後面寫條件判斷,then後面寫當符合條件時,要回傳的值
            { case: { $gte: ["$consume", 1000] }, then: "高級會員" },
            { case: { $gte: ["$consume", 3000] }, then: "VIP會員" }
          ],
          default: "一般會員"  // 當所有條件不符合時,預設會回傳的值
        }
      }
    }
  },
  { $project: { name: 1, level: 1 } }
]);

// 最後回傳的資料
  { id: 1, name: "小美", level: "VIP會員" },
  { id: 2, name: "小王", level: "高級會員" },
  { id: 3, name: "小明", level: "一般會員" }

ps.前面有提到$bucket$facet這兩個操作符,明後天會介紹

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


上一篇
被MongoDB用Aggregate暴打的後端小菜雞日記-day11- 用$sample、$rand隨機取得資料
下一篇
被MongoDB用Aggregate暴打的後端小菜雞日記-day13-$bucket 桶子分組
系列文
被MongoDB用Aggregate暴打的後端小菜雞日記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言