Operator logika menggabungkan beberapa syarat filter menjadi satu query yang lebih spesifik. Topik ini membahas $and untuk syarat yang harus terpenuhi bersama, $or untuk syarat yang cukup terpenuhi salah satunya, serta $not dan $nor untuk pembalikan syarat. Contoh dijalankan pada koleksi anggota perpustakaan yang memuat status keanggotaan, tahun daftar, dan jumlah pinjaman aktif.
Penggabungan AND implisit dan eksplisit#
Penggabungan paling umum terjadi secara implisit. Filter yang menuliskan beberapa field sekaligus sudah berarti AND, yaitu seluruh syarat wajib terpenuhi. Bentuk eksplisit $and diperlukan pada situasi tertentu. Salah satunya adalah ketika operator yang sama perlu ditulis dua kali pada satu field, karena objek filter tidak boleh memuat kunci operator yang berulang. Situasi lainnya adalah penggabungan bersarang antara beberapa operator logika dalam satu query.
Siapkan data contoh berupa delapan anggota perpustakaan.
use perpustakaanswitched to db perpustakaandb.anggota.insertMany([
{ nama: "Ali Rahman", jenis: "reguler", tahunDaftar: 2019, aktif: true, pinjaman: 2 },
{ nama: "Budi Santoso", jenis: "mahasiswa", tahunDaftar: 2021, aktif: true, pinjaman: 1 },
{ nama: "Citra Melati", jenis: "mahasiswa", tahunDaftar: 2020, aktif: false, pinjaman: 0 },
{ nama: "Dewi Kartika", jenis: "reguler", tahunDaftar: 2018, aktif: true, pinjaman: 3 },
{ nama: "Eka Putri", jenis: "guru", tahunDaftar: 2022, aktif: true, pinjaman: 0 },
{ nama: "Farhan Hidayat", jenis: "reguler", tahunDaftar: 2023, aktif: false, pinjaman: 1 },
{ nama: "Gita Lestari", jenis: "mahasiswa", tahunDaftar: 2019, aktif: true, pinjaman: 2 },
{ nama: "Hendra Wijaya", jenis: "guru", tahunDaftar: 2021, aktif: false, pinjaman: 0 }
]){
acknowledged: true,
insertedIds: {
'0': ObjectId('6ae85ec3b1a3fd45fbce5f47'),
'1': ObjectId('6ae85ec3b1a3fd45fbce5f48'),
'2': ObjectId('6ae85ec3b1a3fd45fbce5f49'),
'3': ObjectId('6ae85ec3b1a3fd45fbce5f4a'),
'4': ObjectId('6ae85ec3b1a3fd45fbce5f4b'),
'5': ObjectId('6ae85ec3b1a3fd45fbce5f4c'),
'6': ObjectId('6ae85ec3b1a3fd45fbce5f4d'),
'7': ObjectId('6ae85ec3b1a3fd45fbce5f4e')
}
}Filter implisit menuliskan kedua syarat sebagai field biasa dalam satu objek.
db.anggota.find({ jenis: "mahasiswa", aktif: true })[
{
_id: ObjectId('6ae85ec3b1a3fd45fbce5f48'),
nama: 'Budi Santoso',
jenis: 'mahasiswa',
tahunDaftar: 2021,
aktif: true,
pinjaman: 1
},
{
_id: ObjectId('6ae85ec3b1a3fd45fbce5f4d'),
nama: 'Gita Lestari',
jenis: 'mahasiswa',
tahunDaftar: 2019,
aktif: true,
pinjaman: 2
}
]Hasilnya dua anggota mahasiswa yang masih aktif. Bentuk $and eksplisit diperlukan ketika field pinjaman perlu ditulis dua kali dengan syarat berbeda, yaitu mencari anggota yang pernah meminjam dengan jumlah yang tidak tepat dua.
db.anggota.find({ $and: [ { pinjaman: { $gte: 1 } }, { pinjaman: { $ne: 2 } } ] })[
{
_id: ObjectId('6ae85ec3b1a3fd45fbce5f48'),
nama: 'Budi Santoso',
jenis: 'mahasiswa',
tahunDaftar: 2021,
aktif: true,
pinjaman: 1
},
{
_id: ObjectId('6ae85ec3b1a3fd45fbce5f4a'),
nama: 'Dewi Kartika',
jenis: 'reguler',
tahunDaftar: 2018,
aktif: true,
pinjaman: 3
},
{
_id: ObjectId('6ae85ec3b1a3fd45fbce5f4c'),
nama: 'Farhan Hidayat',
jenis: 'reguler',
tahunDaftar: 2023,
aktif: false,
pinjaman: 1
}
]Hasilnya tiga anggota dengan jumlah pinjaman satu atau tiga. Nilai dua sengaja dikeluarkan dari hasil karena melanggar syarat $ne. Penulisan { pinjaman: { $ne: 2, $ne: 2 } } tentu tidak mungkin dilakukan, sehingga $and eksplisit menjadi satu-satunya bentuk yang sah untuk kombinasi semacam ini.
Operator $or#
Operator $or menerima array berisi beberapa syarat dan mengembalikan dokumen yang memenuhi sekurang-kurangnya satu syarat. Dokumen yang memenuhi lebih dari satu syarat tetap ditampilkan satu kali. Bentuk umumnya adalah { $or: [ syarat1, syarat2 ] }, dengan setiap syarat ditulis sebagai objek filter biasa.
db.anggota.find({ $or: [ { jenis: "guru" }, { pinjaman: { $gte: 3 } } ] })[
{
_id: ObjectId('6ae85ec3b1a3fd45fbce5f4a'),
nama: 'Dewi Kartika',
jenis: 'reguler',
tahunDaftar: 2018,
aktif: true,
pinjaman: 3
},
{
_id: ObjectId('6ae85ec3b1a3fd45fbce5f4b'),
nama: 'Eka Putri',
jenis: 'guru',
tahunDaftar: 2022,
aktif: true,
pinjaman: 0
},
{
_id: ObjectId('6ae85ec3b1a3fd45fbce5f4e'),
nama: 'Hendra Wijaya',
jenis: 'guru',
tahunDaftar: 2021,
aktif: false,
pinjaman: 0
}
]Hasilnya memuat dua anggota berjenis guru dan satu anggota reguler dengan tiga pinjaman aktif. Ketiganya dipilih karena memenuhi salah satu dari kedua syarat tersebut. Isi array $or tidak terbatas pada dua syarat, sehingga tiga syarat atau lebih dapat digabungkan dalam satu array yang sama.
Operator $not#
Operator $not membalik hasil satu syarat pada satu field. Nilainya berupa objek operator yang akan dinegasikan, sehingga { tahunDaftar: { $not: { $gt: 2020 } } } berarti mencari dokumen yang gagal memenuhi syarat tahun lebih besar dari 2020. Operator ini sering digunakan bersama $regex, yaitu operator pencocokan pola teks, atau bersama operator perbandingan yang pembalikannya tidak tersedia secara langsung.
db.anggota.find({ tahunDaftar: { $not: { $gt: 2020 } } })[
{
_id: ObjectId('6ae85ec3b1a3fd45fbce5f47'),
nama: 'Ali Rahman',
jenis: 'reguler',
tahunDaftar: 2019,
aktif: true,
pinjaman: 2
},
{
_id: ObjectId('6ae85ec3b1a3fd45fbce5f49'),
nama: 'Citra Melati',
jenis: 'mahasiswa',
tahunDaftar: 2020,
aktif: false,
pinjaman: 0
},
{
_id: ObjectId('6ae85ec3b1a3fd45fbce5f4a'),
nama: 'Dewi Kartika',
jenis: 'reguler',
tahunDaftar: 2018,
aktif: true,
pinjaman: 3
},
{
_id: ObjectId('6ae85ec3b1a3fd45fbce5f4d'),
nama: 'Gita Lestari',
jenis: 'mahasiswa',
tahunDaftar: 2019,
aktif: true,
pinjaman: 2
}
]Hasilnya empat anggota dengan tahun daftar 2020 ke bawah, termasuk 2018 dan 2019. Hasil yang sama sebenarnya dapat ditulis dengan $lte, tetapi bentuk $not menjadi wajib apabila operator yang dinegasikan tidak punya padanan langsung. Salah satu kesalahan yang sering terjadi adalah memberikan nilai langsung tanpa objek operator.
db.anggota.find({ tahunDaftar: { $not: 2020 } })Uncaught
MongoServerError[BadValue]: $not argument must be a regex or an objectServer menolak query tersebut dengan pesan error MongoServerError[BadValue]: $not argument must be a regex or an object, karena $not hanya menerima objek operator atau pola pencocokan. Bentuk yang benar tetap harus menyatakan operasinya secara lengkap, misalnya { $not: { $eq: 2020 } } apabila maksudnya mengecualikan satu nilai.
Operator $nor#
Operator $nor merupakan pembalikan dari $or, yaitu mengembalikan dokumen yang gagal memenuhi seluruh syarat dalam arraynya. Semakin banyak syarat pada $nor, semakin ketat saringannya, karena satu dokumen harus lolos dari semua pengecualian sekaligus. Bentuk umumnya sama seperti $or, hanya nama operatornya yang berbeda.
db.anggota.find({ $nor: [ { aktif: true }, { pinjaman: 0 } ] })[
{
_id: ObjectId('6ae85ec3b1a3fd45fbce5f4c'),
nama: 'Farhan Hidayat',
jenis: 'reguler',
tahunDaftar: 2023,
aktif: false,
pinjaman: 1
}
]Hasilnya satu anggota, yaitu anggota yang tidak aktif dan tetap memiliki pinjaman berjalan. Kombinasi semacam ini cocok untuk mencari data yang perlu ditindaklanjuti, misalnya daftar keanggotaan yang patut dihubungi kembali. Dokumen yang aktif maupun yang bebas pinjaman sama-sama dikeluarkan dari hasil.
Menggabungkan beberapa operator logika#
Operator logika dapat disusun bertingkat dalam satu query. Syarat pada array $and maupun $or berupa objek filter biasa, dan objek itu sendiri boleh berisi operator logika lain. Pola yang paling sering muncul adalah $and di luar yang menampung beberapa $or di dalamnya, atau sebaliknya.
db.anggota.find({ $and: [ { aktif: true }, { $or: [ { jenis: "mahasiswa" }, { pinjaman: { $gte: 3 } } ] } ] })[
{
_id: ObjectId('6ae85ec3b1a3fd45fbce5f48'),
nama: 'Budi Santoso',
jenis: 'mahasiswa',
tahunDaftar: 2021,
aktif: true,
pinjaman: 1
},
{
_id: ObjectId('6ae85ec3b1a3fd45fbce5f4a'),
nama: 'Dewi Kartika',
jenis: 'reguler',
tahunDaftar: 2018,
aktif: true,
pinjaman: 3
},
{
_id: ObjectId('6ae85ec3b1a3fd45fbce5f4d'),
nama: 'Gita Lestari',
jenis: 'mahasiswa',
tahunDaftar: 2019,
aktif: true,
pinjaman: 2
}
]Query di atas mencari anggota aktif yang berjenis mahasiswa atau memiliki sedikitnya tiga pinjaman. Hasilnya tiga anggota yang memenuhi kedua lapis syarat tersebut. Perhatikan keseimbangan tanda kurung siku dan kurawal pada query bertingkat, karena kesalahan penempatan satu tanda saja akan mengubah makna seluruh filter.
Ringkasan#
- Filter dengan beberapa field sudah bersifat AND, sedangkan
$andeksplisit diperlukan ketika operator yang sama muncul dua kali pada satu field atau ketika syarat disusun bertingkat. $ormengembalikan dokumen yang memenuhi sekurang-kurangnya satu syarat, sedangkan$normengembalikan dokumen yang gagal memenuhi seluruh syarat.$notmembalik satu syarat operator pada satu field dan wajib berisi objek operator, bukan nilai langsung.- Operator logika dapat disarangkan satu sama lain, dengan keseimbangan tanda kurung sebagai penentu makna query.
Referensi#
- $and — MongoDB Manual — Dokumentasi operator logika $and beserta contoh penggabungannya.
- $or — MongoDB Manual — Dokumentasi operator logika $or untuk syarat alternatif.
- $not — MongoDB Manual — Dokumentasi operator $not beserta aturan penulisannya.
- $nor — MongoDB Manual — Dokumentasi operator $nor untuk penolakan seluruh syarat.