sort dan limit

Mengurutkan hasil query dengan sort dan membatasi jumlahnya dengan limit.

Daftar isi

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.

mongosh
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())
text Keluaran
switched to db sensor

Dokumen tersimpan: 8

Baca seluruh dokumen tanpa pengurutan untuk melihat urutan baca bawaan.

mongosh
db.pembacaan.find({}, { _id: 0, menit: 1, sensor: 1, suhu: 1 }).forEach(d => print(JSON.stringify(d)))
text Keluaran
{"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.

mongosh
db.pembacaan.find({}, { _id: 0, menit: 1, sensor: 1, suhu: 1 }).sort({ suhu: 1 }).forEach(d => print(JSON.stringify(d)))
text Keluaran
{"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.

mongosh
db.pembacaan.find({}, { _id: 0, menit: 1, sensor: 1, suhu: 1 }).sort({ suhu: -1 }).forEach(d => print(JSON.stringify(d)))
text Keluaran
{"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.

mongosh
db.pembacaan.find({}, { _id: 0, sensor: 1, suhu: 1 }).sort({ sensor: 1, suhu: -1 }).forEach(d => print(JSON.stringify(d)))
text Keluaran
{"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.

mongosh
db.pembacaan.find({}, { _id: 0, menit: 1, sensor: 1, suhu: 1 }).limit(3).forEach(d => print(JSON.stringify(d)))
text Keluaran
{"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.

mongosh
db.pembacaan.find({}, { _id: 0, sensor: 1, suhu: 1 }).sort({ suhu: -1 }).limit(3).forEach(d => print(JSON.stringify(d)))
text Keluaran
{"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 dan sort({field: -1}) mengurutkan menurun. Beberapa field dapat digabungkan, dengan prioritas mengikuti urutan penulisan.
  • limit(n) membatasi jumlah dokumen yang dikirim server, sedangkan limit(0) berarti tanpa batas.
  • Kombinasi sort dan limit selalu mengurutkan terlebih dahulu, baru membatasi, berapa pun urutan penulisannya pada rantai metode.
  • Urutan hasil tanpa sort tidak dijamin karena mengikuti urutan baca koleksi saat itu.

Referensi#