Hasil query MongoDB tidak dijamin tiba dalam urutan tertentu. Tanpa instruksi pengurutan, server bebas mengirim dokumen dalam urutan yang paling cepat dibaca dari penyimpanannya, dan urutan itu dapat berubah antar eksekusi. Topik ini membahas dua metode pada kursor (cursor), yaitu objek yang mengelola aliran hasil query dari server ke klien. Kedua metodenya adalah sort untuk mengurutkan dokumen dan limit untuk membatasi jumlahnya. Setelah topik ini diikuti, query dapat disusun agar menampilkan dokumen terurut menaik maupun menurun pada satu atau beberapa field. Hasilnya juga dapat dipangkas hingga tersisa beberapa dokumen teratas.
Hasil query tanpa urutan yang dijamin#
MongoDB mengirim hasil query dalam urutan baca koleksi saat itu, yaitu urutan yang ditentukan oleh mesin penyimpanan dan bukan urutan penyisipan yang dijanjikan. Pada koleksi kecil yang baru dibuat, hasil sering tampak berurutan seperti data yang dimasukkan, sehingga kelalaian tidak mengurutkan jarang terasa. Setelah dokumen diperbarui, dihapus, dan disisipkan ulang berkali-kali, urutan baca dapat berubah tanpa pemberitahuan. Aplikasi yang mengandalkan urutan bawaan dengan demikian berisiko menampilkan data dalam susunan yang tidak konsisten.
Siapkan koleksi contoh berisi delapan catatan pengukuran suhu pada basis data sensor. Data sengaja disisipkan dalam urutan menit yang tidak rapi agar perbedaan urutan baca dan urutan field terlihat.
use sensor
const hasil = db.pembacaan.insertMany([{ menit: 4, sensor: "S-02", suhu: 25.6, kelembapan: 70 }, { menit: 0, sensor: "S-01", suhu: 26.4, kelembapan: 71 }, { menit: 7, sensor: "S-02", suhu: 26, kelembapan: 66 }, { menit: 2, sensor: "S-01", suhu: 27.1, kelembapan: 69 }, { menit: 5, sensor: "S-03", suhu: 23.8, kelembapan: 74 }, { menit: 1, sensor: "S-02", suhu: 24.9, kelembapan: 68 }, { menit: 6, sensor: "S-01", suhu: 24.1, kelembapan: 73 }, { menit: 3, sensor: "S-03", suhu: 22.3, kelembapan: 75 }])
print("Dokumen tersimpan: " + db.pembacaan.countDocuments())switched to db sensor
Dokumen tersimpan: 8Baca seluruh dokumen tanpa pengurutan untuk melihat urutan baca bawaan.
db.pembacaan.find({}, { _id: 0, menit: 1, sensor: 1, suhu: 1 }).forEach(d => print(JSON.stringify(d))){"menit":4,"sensor":"S-02","suhu":25.6}
{"menit":0,"sensor":"S-01","suhu":26.4}
{"menit":7,"sensor":"S-02","suhu":26}
{"menit":2,"sensor":"S-01","suhu":27.1}
{"menit":5,"sensor":"S-03","suhu":23.8}
{"menit":1,"sensor":"S-02","suhu":24.9}
{"menit":6,"sensor":"S-01","suhu":24.1}
{"menit":3,"sensor":"S-03","suhu":22.3}Keluaran mengikuti urutan penyisipan karena koleksi masih baru. Jaminan atas urutan itu tidak ada, sehingga pengurutan eksplisit diperlukan setiap kali urutan bermakna bagi aplikasi.
Mengurutkan dengan sort#
Metode sort menerima dokumen spesifikasi pengurutan berupa pasangan field dan arah, yaitu 1 untuk menaik dan -1 untuk menurun. Server mengurutkan dokumen yang cocok sebelum hasil dikirim, sehingga aplikasi menerima dokumen pertama yang sudah berada pada posisi yang benar. Urutkan koleksi contoh berdasarkan suhu menaik untuk mendapatkan pembacaan terdingin lebih dahulu.
db.pembacaan.find({}, { _id: 0, menit: 1, sensor: 1, suhu: 1 }).sort({ suhu: 1 }).forEach(d => print(JSON.stringify(d))){"menit":3,"sensor":"S-03","suhu":22.3}
{"menit":5,"sensor":"S-03","suhu":23.8}
{"menit":6,"sensor":"S-01","suhu":24.1}
{"menit":1,"sensor":"S-02","suhu":24.9}
{"menit":4,"sensor":"S-02","suhu":25.6}
{"menit":7,"sensor":"S-02","suhu":26}
{"menit":0,"sensor":"S-01","suhu":26.4}
{"menit":2,"sensor":"S-01","suhu":27.1}Mengubah arah menjadi -1 membalik susunannya, sehingga pembacaan terpanas muncul lebih dahulu.
db.pembacaan.find({}, { _id: 0, menit: 1, sensor: 1, suhu: 1 }).sort({ suhu: -1 }).forEach(d => print(JSON.stringify(d))){"menit":2,"sensor":"S-01","suhu":27.1}
{"menit":0,"sensor":"S-01","suhu":26.4}
{"menit":7,"sensor":"S-02","suhu":26}
{"menit":4,"sensor":"S-02","suhu":25.6}
{"menit":1,"sensor":"S-02","suhu":24.9}
{"menit":6,"sensor":"S-01","suhu":24.1}
{"menit":5,"sensor":"S-03","suhu":23.8}
{"menit":3,"sensor":"S-03","suhu":22.3}Mengurutkan berdasarkan beberapa field#
Dokumen spesifikasi pengurutan boleh memuat lebih dari satu field. Field pertama menjadi urutan utama, sedangkan field kedua hanya dipakai untuk memecah posisi dokumen yang nilai field pertamanya sama, dan seterusnya. Arah setiap field ditentukan sendiri-sendiri sehingga kombinasi seperti menaik lalu menurun sah digunakan. Contoh berikut mengurutkan berdasarkan sensor menaik, lalu suhu menurun untuk menampilkan pembacaan terpanas dari setiap sensor.
db.pembacaan.find({}, { _id: 0, sensor: 1, suhu: 1 }).sort({ sensor: 1, suhu: -1 }).forEach(d => print(JSON.stringify(d))){"sensor":"S-01","suhu":27.1}
{"sensor":"S-01","suhu":26.4}
{"sensor":"S-01","suhu":24.1}
{"sensor":"S-02","suhu":26}
{"sensor":"S-02","suhu":25.6}
{"sensor":"S-02","suhu":24.9}
{"sensor":"S-03","suhu":23.8}
{"sensor":"S-03","suhu":22.3}Keluaran menunjukkan ketiga dokumen dengan sensor S-01 tersusun dari suhu 27.1 ke 24.1, kemudian pola yang sama berlaku untuk S-02 dan S-03. Bila arah kedua field dibalik, urutan utama tetap berada pada field pertama, sedangkan yang berubah hanya pembacaan di dalam tiap sensor.
Membatasi hasil dengan limit#
Metode limit mengatur jumlah maksimum dokumen yang dikirim server untuk satu query. Tanpa limit, kursor tetap mengirim seluruh dokumen yang cocok dalam batch demi batch hingga habis. Dengan limit, server berhenti mengirim hasil begitu jumlah maksimum tercapai, sehingga kerja jaringan dan memori ikut berhemat. Panggil limit setelah find dengan angka jumlah dokumen yang diinginkan.
db.pembacaan.find({}, { _id: 0, menit: 1, sensor: 1, suhu: 1 }).limit(3).forEach(d => print(JSON.stringify(d))){"menit":4,"sensor":"S-02","suhu":25.6}
{"menit":0,"sensor":"S-01","suhu":26.4}
{"menit":7,"sensor":"S-02","suhu":26}Tiga dokumen pada keluaran mengikuti urutan baca koleksi, bukan dokumen dengan suhu tertinggi maupun terendah. Limit hampir selalu dipakai bersama sort ketika tujuannya memilih dokumen teratas, misalnya tiga pembacaan terpanas.
Rangkai sort dan limit pada rantai yang sama untuk memotong hasil yang sudah terurut.
db.pembacaan.find({}, { _id: 0, sensor: 1, suhu: 1 }).sort({ suhu: -1 }).limit(3).forEach(d => print(JSON.stringify(d))){"sensor":"S-01","suhu":27.1}
{"sensor":"S-01","suhu":26.4}
{"sensor":"S-02","suhu":26}Pada rantai di atas, sort ditulis sebelum limit, dan MongoDB menerapkan pengurutan terlebih dahulu, baru pembatasan. Urutan penulisan metode pada rantai tidak mengubah makna query, sehingga hasilnya selalu tiga dokumen dengan suhu tertinggi.
Ringkasan#
sort({field: 1})mengurutkan hasil menaik dansort({field: -1})mengurutkan menurun. Beberapa field dapat digabungkan, dengan prioritas mengikuti urutan penulisan.limit(n)membatasi jumlah dokumen yang dikirim server, sedangkanlimit(0)berarti tanpa batas.- Kombinasi sort dan limit selalu mengurutkan terlebih dahulu, baru membatasi, berapa pun urutan penulisannya pada rantai metode.
- Urutan hasil tanpa
sorttidak dijamin karena mengikuti urutan baca koleksi saat itu.
Referensi#
- cursor.sort() — MongoDB Documentation — Spesifikasi arah pengurutan beserta urutan tipe BSON.
- cursor.limit() — MongoDB Documentation — Perilaku pembatasan jumlah dokumen, termasuk kasus limit bernilai 0.
- MongoDB Manual — MongoDB Documentation — Dokumentasi resmi MongoDB sebagai rujukan umum seluruh topik pada jalur ini.