Proyeksi (projection) menentukan field mana yang dikembalikan sebuah query pada satu koleksi. Topik ini membahas proyeksi penyertaan yang memilih sebagian field, proyeksi pengecualian yang membuang field tertentu, larangan mencampur kedua bentuk tersebut, proyeksi field bersarang dengan notasi titik, sampai pemotongan array dengan operator $slice. Seluruh contoh dijalankan pada koleksi buku di basis data perpustakaan, sehingga bentuk hasil setiap query dapat dibandingkan langsung dengan isi dokumennya.
Menyertakan field tertentu#
Metode find menerima argumen kedua berupa dokumen proyeksi. Setiap field yang ingin disertakan diberi nilai 1, sedangkan field di luar daftar tidak ikut dikembalikan. Bentuk seperti ini disebut proyeksi penyertaan (inclusion) karena daftarnya menyatakan field yang ingin dipertahankan. Field _id diperlakukan khusus karena server menyertakannya secara otomatis meskipun tidak dituliskan pada dokumen proyeksi.
Siapkan data contoh berupa lima buku yang masing-masing memuat array tags dan subdokumen letak.
use perpustakaanswitched to db perpustakaandb.buku.insertMany([
{ judul: "Dasar Jaringan Komputer", pengarang: "Ali Rahman", tahun: 2019, stok: 3, tags: ["jaringan", "teknik"], letak: { rak: "A", tingkat: 2 } },
{ judul: "Algoritma dan Struktur Data", pengarang: "Budi Santoso", tahun: 2021, stok: 5, tags: ["pemrograman", "algoritma", "struktur data"], letak: { rak: "B", tingkat: 1 } },
{ judul: "Pemrograman Web Praktis", pengarang: "Dewi Kartika", tahun: 2022, stok: 4, tags: ["web", "pemrograman", "frontend", "backend"], letak: { rak: "C", tingkat: 3 } },
{ judul: "Statistika Terapan", pengarang: "Rina Wulandari", tahun: 2020, stok: 1, tags: ["statistika"], letak: { rak: "A", tingkat: 4 } },
{ judul: "Kriptografi Dasar", pengarang: "Eka Prasetyo", tahun: 2023, stok: 6, tags: ["keamanan", "matematika"], letak: { rak: "D", tingkat: 1 } }
]){
acknowledged: true,
insertedIds: {
'0': ObjectId('6ae8937819c74f1b3f8de666'),
'1': ObjectId('6ae8937819c74f1b3f8de667'),
'2': ObjectId('6ae8937819c74f1b3f8de668'),
'3': ObjectId('6ae8937819c74f1b3f8de669'),
'4': ObjectId('6ae8937819c74f1b3f8de66a')
}
}Saring buku terbitan 2021 ke atas dengan proyeksi yang hanya menyertakan judul dan pengarangnya.
db.buku.find({ tahun: { $gte: 2021 } }, { judul: 1, pengarang: 1 })[
{
_id: ObjectId('6ae8726ff4fdb3d3e98de667'),
judul: 'Algoritma dan Struktur Data',
pengarang: 'Budi Santoso'
},
{
_id: ObjectId('6ae8726ff4fdb3d3e98de668'),
judul: 'Pemrograman Web Praktis',
pengarang: 'Dewi Kartika'
},
{
_id: ObjectId('6ae8726ff4fdb3d3e98de66a'),
judul: 'Kriptografi Dasar',
pengarang: 'Eka Prasetyo'
}
]Hasilnya tiga dokumen dengan struktur yang jauh lebih ramping daripada dokumen aslinya karena field tahun, stok, tags, dan letak tidak ikut dikirim. Field _id tetap hadir pada setiap dokumen meskipun tidak dinyatakan dalam proyeksi. Apabila _id tidak dibutuhkan, kecualikan field tersebut secara eksplisit dengan nilai 0.
db.buku.find({ pengarang: "Dewi Kartika" }, { _id: 0, judul: 1, tahun: 1 })[ { judul: 'Pemrograman Web Praktis', tahun: 2022 } ]Hasilnya satu dokumen yang hanya memuat judul dan tahun. Kombinasi _id: 0 dengan field bernilai 1 tetap terhitung proyeksi penyertaan yang sah karena _id merupakan satu-satunya field yang boleh dikecualikan dari mode ini. Pola seperti ini berguna ketika hasil query langsung dikonsumsi oleh proses yang tidak memerlukan identitas dokumen, misalnya laporan ringkas.
Mengecualikan field tertentu#
Bentuk kedua proyeksi adalah proyeksi pengecualian (exclusion), yaitu menyatakan field yang ingin dibuang dengan nilai 0, sedangkan seluruh field lain tetap dikembalikan utuh. Bentuk ini tepat dipakai ketika dokumen memuat banyak field dan hanya sedikit yang perlu disembunyikan. Pada data buku, field stok dan letak merupakan data internal gudang yang tidak perlu tampil pada daftar katalog.
db.buku.find({ pengarang: "Dewi Kartika" }, { stok: 0, letak: 0 })[
{
_id: ObjectId('6ae8726ff4fdb3d3e98de668'),
judul: 'Pemrograman Web Praktis',
pengarang: 'Dewi Kartika',
tahun: 2022,
tags: [ 'web', 'pemrograman', 'frontend', 'backend' ]
}
]Hasilnya satu dokumen yang memuat _id, judul, pengarang, tahun, dan tags, tanpa stok dan letak. Array tags ikut dikembalikan karena tidak masuk daftar pengecualian, sehingga isi arraynya tetap dapat dibaca.
Pemilihan antara kedua bentuk proyeksi mengikuti isi dokumennya. Gunakan proyeksi pengecualian apabila field yang dibuang lebih sedikit daripada yang dipertahankan, karena daftar proyeksinya lebih pendek. Proyeksi pengecualian juga lebih tahan terhadap perubahan struktur karena field baru yang ditambahkan pada dokumen tetap dikembalikan secara otomatis. Sebaliknya, proyeksi penyertaan harus diperbarui satu per satu setiap kali field baru mulai digunakan.
Larangan mencampur kedua mode#
Satu dokumen proyeksi hanya boleh memakai satu mode, yaitu penyertaan saja atau pengecualian saja. Aturan ini berlaku pada seluruh field biasa, sedangkan _id tetap boleh dikecualikan dari proyeksi penyertaan. Campuran kedua mode pada field biasa ditolak server dengan error, sebagaimana terlihat pada query berikut.
db.buku.find({}, { judul: 1, stok: 0 })Uncaught
MongoServerError[Location31254]: Cannot do exclusion on field stok in inclusion projectionPesan error Cannot do exclusion on field stok in inclusion projection muncul karena nilai 1 pada judul membuat seluruh dokumen proyeksi dianggap mode penyertaan, sehingga stok: 0 terbaca sebagai pelanggaran di dalam mode tersebut. Server tidak menafsirkan campuran itu sebagai daftar field yang tersisa, sehingga query dihentikan sebelum dieksekusi. Perbaikannya adalah memilih satu mode secara konsisten, misalnya { judul: 1 } apabila hanya judul yang dibutuhkan, atau { stok: 0 } apabila hanya stok yang ingin dibuang. Aturan satu mode ini membuat maksud proyeksi selalu tunggal, sehingga server tidak perlu menduga field mana yang dimaksudkan penyertaan dan mana yang dimaksudkan pengecualian.
Proyeksi field bersarang#
Field yang berada di dalam subdokumen diproyeksikan dengan notasi titik. Penulisan "letak.rak": 1 menyertakan field rak saja, bukan seluruh subdokumen letak. Nama field bersarang ditulis dalam tanda kutip karena tanda titik pada nama field hanya sah di dalam string.
db.buku.find({ "letak.tingkat": { $lte: 2 } }, { judul: 1, "letak.rak": 1 })[
{
_id: ObjectId('6ae8726ff4fdb3d3e98de666'),
judul: 'Dasar Jaringan Komputer',
letak: { rak: 'A' }
},
{
_id: ObjectId('6ae8726ff4fdb3d3e98de667'),
judul: 'Algoritma dan Struktur Data',
letak: { rak: 'B' }
},
{
_id: ObjectId('6ae8726ff4fdb3d3e98de66a'),
judul: 'Kriptografi Dasar',
letak: { rak: 'D' }
}
]Hasilnya tiga buku dengan objek letak yang hanya memuat field rak, sedangkan field tingkat tidak ikut dikirim. Apabila proyeksinya ditulis { judul: 1, letak: 1 }, seluruh isi subdokumen letak akan dikembalikan termasuk tingkat. Perlu diingat bahwa notasi titik pada proyeksi hanya memilih field, bukan menyaring isi, sehingga syarat pencocokannya tetap ditulis pada argumen filter metode find. Pilihan bentuk ini menentukan ukuran keluaran sekaligus data yang terekspos ke aplikasi, sehingga field bersarang sebaiknya dipangkas sampai bagian yang benar-benar dipakai saja.
Proyeksi pengecualian menerima notasi titik dengan cara yang sama, sehingga { "letak.tingkat": 0 } membuang field tingkat saja dan mempertahankan field lain di dalam subdokumen letak. Bentuk { letak: 0 } tetap dipakai apabila seluruh isi subdokumen ingin dibuang. Pemilihan di antara keduanya mengikuti kebutuhan keluaran, yaitu memangkas sebagian field atau menyembunyikan subdokumen sepenuhnya.
Memotong array dengan $slice#
Operator $slice memotong isi array pada hasil query tanpa mengubah data yang tersimpan. Bentuk { $slice: 2 } mengambil dua elemen pertama array, sedangkan elemen di belakangnya tidak ikut dikembalikan. Buku Pemrograman Web Praktis menyimpan empat label pada array tags, sehingga cocok sebagai contoh pemotongannya.
db.buku.find({ judul: "Pemrograman Web Praktis" }, { judul: 1, tags: { $slice: 2 } })[
{
_id: ObjectId('6ae8726ff4fdb3d3e98de668'),
judul: 'Pemrograman Web Praktis',
tags: [ 'web', 'pemrograman' ]
}
]Hasilnya array tags hanya memuat dua elemen pertama. Nilai negatif memotong dari akhir array, sehingga { $slice: -2 } mengambil dua elemen terakhirnya. Pemotongan ini hanya berlaku pada tampilan karena data aslinya tidak tersentuh.
db.buku.find({ judul: "Pemrograman Web Praktis" }, { judul: 1, tags: { $slice: -2 } })[
{
_id: ObjectId('6ae8726ff4fdb3d3e98de668'),
judul: 'Pemrograman Web Praktis',
tags: [ 'frontend', 'backend' ]
}
]Bentuk ketiga berupa array [lompat, ambil], yaitu melewati sejumlah elemen di awal sebelum memotong. Kombinasi [1, 2] berarti melewati satu elemen pertama, lalu mengambil dua elemen berikutnya. Bentuk ini berguna ketika bagian awal array sudah diketahui dan tidak dibutuhkan pada hasilnya.
db.buku.find({ judul: "Pemrograman Web Praktis" }, { judul: 1, tags: { $slice: [1, 2] } })[
{
_id: ObjectId('6ae8726ff4fdb3d3e98de668'),
judul: 'Pemrograman Web Praktis',
tags: [ 'pemrograman', 'frontend' ]
}
]$slice dapat dituliskan bersama daftar penyertaan pada satu dokumen proyeksi yang sama, sebagaimana ketiga contoh di atas, sehingga field yang disertakan dan array yang dipotong dinyatakan sekaligus. Operator ini juga sah ditulis sendirian pada dokumen proyeksi, misalnya { tags: { $slice: 2 } }. Pada bentuk sendirian tersebut, field-field lain tetap dikembalikan utuh dan hanya arraynya yang terpotong.
Ringkasan#
- Proyeksi penyertaan menyatakan field yang dipertahankan dengan nilai 1, sedangkan proyeksi pengecualian menyatakan field yang dibuang dengan nilai 0.
- Field
_iddisertakan secara otomatis dan menjadi satu-satunya field yang boleh dikecualikan dari proyeksi penyertaan. - Campuran nilai 1 dan 0 pada field biasa ditolak server dengan error, sehingga satu dokumen proyeksi hanya memakai satu mode.
- Field bersarang diproyeksikan dengan notasi titik, dan
$slicememotong array pada keluaran melalui tiga bentuk nilai, yaitu jumlah positif, jumlah negatif, dan pasangan[lompat, ambil].
Referensi#
- Project Fields to Return from Query — MongoDB Manual — Tutorial resmi penulisan proyeksi pada hasil query.
- db.collection.find() — MongoDB Manual — Dokumentasi metode find beserta argumen proyeksinya.
- $slice (projection) — MongoDB Manual — Dokumentasi operator proyeksi $slice untuk pemotongan array.