Label “premium” untuk buku di atas Rp100.000, status “terlaris” untuk yang laku 200 eksemplar, teks “belum ada ulasan” untuk buku tanpa ulasan — semua nilai ini tidak disimpan di database, melainkan diturunkan dari kondisi data. Di kode aplikasi biasa kita menulis if/else; di dalam pipeline aggregation, peran itu dipegang conditional expressions: $cond, $switch, dan $ifNull. Chapter ini menguji ketiganya di dalam $project dan $set.
Peta materi Chapter ini:
$conddalam dua bentuk: array tiga element dan objectif/then/else.$switchdenganbranchesdandefault.$ifNulluntuk field yang bisa kosong, beserta kombinasi ketiganya dalam satu stage.
Tiga Operator dan Bentuknya #
Ringkasan bentuknya sebelum kita praktik:
| Operator | Bentuk | Peran |
|---|---|---|
$cond | [ syarat, nilaiBenar, nilaiSalah ] | if-then-else paling ringkas |
$cond | { if: syarat, then: ..., else: ... } | bentuk object, lebih terbaca |
$switch | { branches: [...], default: ... } | banyak kondisi berurutan |
$ifNull | [ ekspresi, nilaiCadangan ] | penanganan null / field hilang |
Semuanya adalah expression, bukan stage — tempatnya di nilai field pada $project, $set, atau di dalam expression lain. Siapkan data uji standar Section ini:
use latihan_agregasi2
db.dropDatabase()
db.buku.insertMany([
{ judul: "Laut Bercerita", penulis: "Leila S. Chudori", harga: 98000, kategori: "fiksi", terjual: 120, tanggal_terbit: ISODate("2017-02-01T00:00:00Z"), tag: ["fiksi", "sastra", "penghargaan"], ulasan: [ { pengulas: "Budi", bintang: 5 }, { pengulas: "Siti", bintang: 4 } ] },
{ judul: "Bumi", penulis: "Tere Liye", harga: 89000, kategori: "fiksi", terjual: 250, tanggal_terbit: ISODate("2014-09-02T00:00:00Z"), tag: ["fiksi", "remaja", "fantasi"], ulasan: [ { pengulas: "Dewi", bintang: 5 }, { pengulas: "Budi", bintang: 4 }, { pengulas: "Siti", bintang: 5 } ] },
{ judul: "Filosofi Teras", penulis: "Henry Manampiring", harga: 89000, kategori: "nonfiksi", terjual: 180, tanggal_terbit: ISODate("2018-07-01T00:00:00Z"), tag: ["filsafat", "pengembangan diri"], ulasan: [ { pengulas: "Siti", bintang: 5 } ] },
{ judul: "Atomic Habits", penulis: "James Clear", harga: 115000, kategori: "nonfiksi", terjual: 310, tanggal_terbit: ISODate("2018-10-16T00:00:00Z"), tag: ["pengembangan diri", "terjemahan"], ulasan: [ { pengulas: "Budi", bintang: 5 }, { pengulas: "Dewi", bintang: 4 } ] },
{ judul: "Rumah Kaca", penulis: "Tere Liye", harga: 72000, kategori: "fiksi", terjual: 120, tanggal_terbit: ISODate("2016-06-15T00:00:00Z"), tag: ["fiksi", "remaja"], ulasan: [ { pengulas: "Dewi", bintang: 4 } ] },
{ judul: "Bumi Manusia", penulis: "Pramoedya A. Toer", harga: 105000, kategori: "sastra", terjual: 150, tanggal_terbit: ISODate("1980-05-25T00:00:00Z"), tag: ["sastra", "sejarah"], ulasan: [ { pengulas: "Budi", bintang: 5 }, { pengulas: "Siti", bintang: 5 }, { pengulas: "Dewi", bintang: 4 } ] },
{ judul: "Hujan Bulan Juni", penulis: "Sapardi Djoko Damono", harga: 65000, kategori: "puisi", terjual: 75, tanggal_terbit: ISODate("1994-06-10T00:00:00Z"), tag: ["puisi", "sastra"] },
{ judul: "Ensiklopedia Sains Populer", penulis: "Tim Sains", harga: 250000, kategori: "referensi", terjual: 40, tanggal_terbit: ISODate("2020-03-05T00:00:00Z"), tag: ["referensi", "sains"], ulasan: [ { pengulas: "Dewi", bintang: 4 } ] }
])Output yang Dihasilkan:
switched to db latihan_agregasi2
{ ok: 1, dropped: 'latihan_agregasi2' }
{
acknowledged: true,
insertedIds: {
'0': ObjectId('6ad3a579849bf064f7ab0050'),
'1': ObjectId('6ad3a579849bf064f7ab0051'),
'2': ObjectId('6ad3a579849bf064f7ab0052'),
'3': ObjectId('6ad3a579849bf064f7ab0053'),
'4': ObjectId('6ad3a579849bf064f7ab0054'),
'5': ObjectId('6ad3a579849bf064f7ab0055'),
'6': ObjectId('6ad3a579849bf064f7ab0056'),
'7': ObjectId('6ad3a579849bf064f7ab0057')
}
}$cond: If-Then-Else dalam Dua Bentuk #
$cond menuntut tiga hal: syarat, nilai bila benar, nilai bila salah. Dua bentuk di bawah ini semantiknya persis sama — pilih array untuk keringkasan, object untuk kejelasan saat expression-nya panjang:
db.buku.aggregate([
{ $limit: 4 },
{ $project: { _id: 0, judul: 1, harga: 1,
labelArray: { $cond: [ { $gte: ["$harga", 100000] }, "premium", "reguler" ] },
labelObjek: { $cond: { if: { $gte: ["$harga", 100000] }, then: "premium", else: "reguler" } } } }
])Output yang Dihasilkan:
[
{
judul: 'Laut Bercerita',
harga: 98000,
labelArray: 'reguler',
labelObjek: 'reguler'
},
{
judul: 'Bumi',
harga: 89000,
labelArray: 'reguler',
labelObjek: 'reguler'
},
{
judul: 'Filosofi Teras',
harga: 89000,
labelArray: 'reguler',
labelObjek: 'reguler'
},
{
judul: 'Atomic Habits',
harga: 115000,
labelArray: 'premium',
labelObjek: 'premium'
}
]Dua kolom label menghasilkan nilai yang sama untuk setiap buku karena keduanya mengevaluasi syarat yang identik: harga >= 100000. Bumi (89.000) dan Laut Bercerita (98.000) mendapat reguler; Atomic Habits (115.000) mendapat premium. Syarat boleh berupa expression bertingkat apa pun — $gte, $and, perbandingan hasil hitung — asalkan bernilai boolean.
$switch: Banyak Kondisi Berurutan #
Saat cabangnya lebih dari dua, $cond bertingkat cepat menjadi sulit dibaca. $switch menerima daftar branches yang diperiksa berurutan — case pertama yang benar menentukan then yang diambil:
db.buku.aggregate([
{ $project: { _id: 0, judul: 1, terjual: 1,
status: { $switch: {
branches: [
{ case: { $gte: ["$terjual", 200] }, then: "terlaris" },
{ case: { $gte: ["$terjual", 100] }, then: "populer" }
],
default: "biasa"
} } } },
{ $sort: { terjual: -1 } }
])Output yang Dihasilkan:
[
{ judul: 'Atomic Habits', terjual: 310, status: 'terlaris' },
{ judul: 'Bumi', terjual: 250, status: 'terlaris' },
{ judul: 'Filosofi Teras', terjual: 180, status: 'populer' },
{ judul: 'Bumi Manusia', terjual: 150, status: 'populer' },
{ judul: 'Laut Bercerita', terjual: 120, status: 'populer' },
{ judul: 'Rumah Kaca', terjual: 120, status: 'populer' },
{ judul: 'Hujan Bulan Juni', terjual: 75, status: 'biasa' },
{ judul: 'Ensiklopedia Sains Populer', terjual: 40, status: 'biasa' }
]Urutan branches menentukan hasilnya: Filosofi Teras (180) tidak memenuhi >= 200, tetapi lolos >= 100 sehingga berstatus populer. Bila tidak ada case yang cocok, default yang diambil — pada contoh ini yang jatuh ke default adalah Hujan Bulan Juni (75) dan Ensiklopedia Sains Populer (40).
$ifNull: Penanganan Field Hilang #
$ifNull menerima pasangan [ ekspresi, nilaiCadangan ]: bila ekspresi bernilai null atau field-nya tidak ada, dikembalikan nilai cadangan; bila tidak, nilai aslinya diteruskan apa adanya. Hujan Bulan Juni adalah buku satu-satunya tanpa field ulasan:
db.buku.aggregate([
{ $project: { _id: 0, judul: 1,
keteranganUlasan: { $ifNull: [ "$ulasan", "belum ada ulasan" ] } } },
{ $match: { judul: { $in: ["Hujan Bulan Juni", "Bumi"] } } }
])Output yang Dihasilkan:
[
{
judul: 'Bumi',
keteranganUlasan: [
{ pengulas: 'Dewi', bintang: 5 },
{ pengulas: 'Budi', bintang: 4 },
{ pengulas: 'Siti', bintang: 5 }
]
},
{ judul: 'Hujan Bulan Juni', keteranganUlasan: 'belum ada ulasan' }
]Hasilnya kontras jelas: Bumi yang punya ulasan meneruskan array aslinya tanpa diubah, sedangkan Hujan Bulan Juni yang tanpa field ulasan menerima teks cadangan. Pola yang sama nanti kita pakai berulang kali di Chapter Operator Array — misalnya $size yang error pada field hilang ditenangkan dengan $ifNull: ["$ulasan", []].
Ketiganya dalam Satu Stage #
Dalam praktik, ketiga operator ini dipakai bersamaan di satu $set untuk membentuk field turunan sekaligus:
db.buku.aggregate([
{ $match: { judul: { $in: ["Hujan Bulan Juni", "Bumi", "Atomic Habits"] } } },
{ $set: {
labelHarga: { $cond: [ { $gte: ["$harga", 100000] }, "premium", "reguler" ] },
status: { $switch: {
branches: [
{ case: { $gte: ["$terjual", 200] }, then: "terlaris" },
{ case: { $gte: ["$terjual", 100] }, then: "populer" }
],
default: "biasa"
} },
keteranganUlasan: { $ifNull: [ "$ulasan", "belum ada ulasan" ] }
} },
{ $project: { _id: 0, judul: 1, labelHarga: 1, status: 1, keteranganUlasan: 1 } }
])Output yang Dihasilkan:
[
{
judul: 'Bumi',
labelHarga: 'reguler',
status: 'terlaris',
keteranganUlasan: [
{ pengulas: 'Dewi', bintang: 5 },
{ pengulas: 'Budi', bintang: 4 },
{ pengulas: 'Siti', bintang: 5 }
]
},
{
judul: 'Atomic Habits',
labelHarga: 'premium',
status: 'terlaris',
keteranganUlasan: [ { pengulas: 'Budi', bintang: 5 }, { pengulas: 'Dewi', bintang: 4 } ]
},
{
judul: 'Hujan Bulan Juni',
labelHarga: 'reguler',
status: 'biasa',
keteranganUlasan: 'belum ada ulasan'
}
]Tiga buku, tiga situasi berbeda: Atomic Habits premium dan terlaris, Bumi reguler namun terlaris, Hujan Bulan Juni reguler, biasa, dan tanpa ulasan. Satu stage $set menghasilkan ketiga kolom turunan itu tanpa menyentuh data asli di collection.
Rangkuman #
$condadalah if-then-else: bentuk array[syarat, benar, salah]dan bentuk object{if, then, else}semantiknya identik.$switchmemeriksabranchesberurutan dan mengambildefaultbila tak ada yang cocok — tanpadefault, input yang tak tercakup memicu error.$ifNullmenggantikannull/field hilang dengan nilai cadangan; nilai lain diteruskan tanpa diubah.- Ketiganya adalah expression, bukan stage — tempatnya di
$project,$set, atau expression lain.
Kondisi yang sering kita uji di chapter ini membandingkan angka. Kondisi lain yang sama seringnya menyangkut tanggal — “buku tahun berapa?”, “laporan per bulan” — dan itulah materi Chapter Operator Tanggal berikutnya.