相信大家在寫程式碼的時候,一定都會用到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
這兩個操作符,明後天會介紹
本篇文章同步放在我的部落格,大家有空可以進來逛逛