Dok Perpustakaan Saya

Sidebar Multi-root

flex-layout

  • Getting Started

  • Guides

  • Reference

typed-rx-http

  • Getting Started

  • Guides

  • Reference

global-rx-state

  • Getting Started

  • Guides

  • Reference

webflux-fe-dev-assistant

reactive-mongo-dsl

Ikhtisar

Sebuah helper kecil untuk pengembang RDBMS yang pertama kali menggunakan MongoDB tumbuh mengikuti kebutuhan proyek nyata, menjelaskan sejarah dan kriteria desain hingga menjadi lapisan kenyamanan MongoDB yang berbasis Driver-first di 1.0.0.


Kisah asal

Saya telah mengembangkan selama sekitar 4 tahun dengan fokus pada RDBMS dan sebagian besar terbiasa dengan lingkungan AWS RDS. Ketika memulai proyek pribadi baru, saya memilih MongoDB untuk pertama kalinya, dan semakin saya mengenalnya, saya merasa itu adalah alat yang dapat secara signifikan mengubah produktivitas pengembangan saya, bukan hanya database dengan skema yang fleksibel.

Terutama MongoDB Atlas terasa seperti dunia baru bagi saya. Saya dapat menggunakan pencarian profesional dan pencarian vektor dalam satu platform data, yang sebelumnya saya pikir harus menggunakan sistem terpisah, dan tugas operasional seperti cadangan, pemantauan, dan penskalaan jauh lebih nyaman dibandingkan dengan standar saya yang hanya menggunakan AWS RDS. Jika diperlukan skala dan fungsi yang lebih profesional, saya bisa memisahkan mesin pencari atau database vektor sebagai layanan terpisah, tetapi dalam tahap membuat dan mengoperasikan proyek dengan cepat, jangkauan yang dapat diselesaikan hanya dengan Atlas sangat menarik.

Masalahnya adalah bahwa menulis kueri dinamis terasa sangat lambat bagi saya yang baru pertama kali menggunakan MongoDB. Awalnya, bentuk findBy... dari repository sudah cukup, tetapi ketika kondisi pencarian menjadi kompleks, saya harus merakit Query, Criteria, dan ekspresi operator secara langsung. Dalam keadaan yang tidak familiar, merakit kondisi yang berulang rentan terhadap kesalahan ketik, dan terus menulis kode dengan bentuk yang sama sangat memperlambat kecepatan pengembangan.

Dimulai dari DSL sederhana untuk pencarian

Jadi, yang pertama saya buat adalah kelas kecil untuk membuat R dari CRUD dengan sederhana. Ini adalah titik awal dari kelas yang sekarang dikenal sebagai ReactiveMongoDsl. Saat itu, tidak ada fitur seperti agregasi, pipeline, atau lookup, dan hanya merakit Query, Criteria, dan paging dari Spring Data ReactiveMongoTemplate sedikit lebih cepat. Saya pikir cukup menggunakan ReactiveMongoTemplate dasar atau MongoDB Driver secara langsung untuk sisa pekerjaan.

Namun, pemikiran rekan pengembang saya berbeda. Dia juga baru pertama kali menggunakan MongoDB, dan setiap kali dia membutuhkan operasi seperti upsert atau bulk, dia selalu bertanya apakah DSL yang saya buat memiliki fitur tersebut. Saya bisa saja menyuruhnya menggunakan API dasar secara langsung, tetapi saya berpikir dia juga akan mengalami kesulitan yang sama seperti yang saya rasakan saat pertama kali belajar MongoDB. Jadi, saya mulai menambahkan satu per satu fitur yang diperlukan ke ReactiveMongoDsl setiap kali fitur baru muncul.

Awalnya, itu sekitar 600 baris, dan ketika mencapai 1.000 baris, saya merasa tidak perlu membagi menjadi beberapa kelas. Ketika mencapai sekitar 2.000 baris, saya sedikit ragu, tetapi struktur untuk pemisahan justru terasa semakin besar, dan yang terpenting, saya jujur merasa malas untuk melakukan pekerjaan itu. Ketika melewati 5.000 baris, saya tidak bisa menunda lebih lama dan memindahkan beberapa fitur yang dapat dipisahkan ke luar, tetapi sudah dalam keadaan yang berat untuk membagi alur inti dengan rinci. Alasan mengapa kelas inti besar bukan karena saya merancang DSL yang besar sejak awal, tetapi lebih karena sejarah penumpukan fitur yang diperlukan dalam proyek nyata di titik masuk yang sama.

Setelah menambahkan pencarian, agregasi, lookup, pembaruan atom, bulk, riwayat, Atlas Search, dan Vector Search, saya menyadari bahwa sebagian besar fitur yang sering saya butuhkan saat menggunakan MongoDB dalam proyek Java sudah ada. Alih-alih hanya menjadi helper internal dalam satu proyek, saya memisahkannya agar dapat digunakan dengan cara yang sama di beberapa proyek, dan itulah proses kelahiran reactive-mongo-dsl.

Dari helper Spring menjadi perpustakaan berbasis Driver-first

Titik awalnya adalah helper untuk menggunakan ReactiveMongoTemplate dengan lebih nyaman, tetapi seiring bertambahnya fitur dan mulai digunakan kembali di beberapa proyek, saya merasa bahwa model eksekusi dari kerangka kerja tertentu tidak seharusnya menjadi batasan perpustakaan. Inti dari 1.0.0 adalah menggunakan MongoExecutionContext sebagai kontrak eksekusi dan langsung menggunakan MongoDB Reactive Streams Driver.

Perubahan ini bukan untuk mengecualikan Spring Data MongoDB. Dalam aplikasi Spring, Anda dapat menghubungkan penamaan koleksi ReactiveMongoTemplate, MongoConverter, konversi kustom, dan audit reaktif dengan adapter MongoExecutionContext. Intinya diletakkan secara independen dari kerangka kerja, dan hanya aplikasi yang diperlukan yang melanjutkan pengaturan Spring yang ada.

Pada saat yang sama, arah untuk tidak mengimplementasikan kembali fitur yang sudah disediakan dengan baik oleh MongoDB Driver di dalam DSL menjadi lebih jelas. Agregasi umum dapat menerima stage Bson secara langsung, dan untuk Search/Vector ada escape hatch seperti SearchOperator, VectorSearchQuery, driverOptions(...), stage(Bson). Ini adalah pilihan untuk memungkinkan penggunaan fitur baru yang disediakan oleh Driver tanpa menunggu rilis berikutnya dari DSL.

Filosofi pengembangan

Tidak menyembunyikan MongoDB

Saya tidak ingin membuat ORM yang mengubah fitur MongoDB menjadi konsep database lain. Saya menghubungkan kueri, agregasi, transaksi, Atlas Search, dan Vector Search MongoDB dengan alur yang lebih singkat dan mudah ditemukan.

Hanya menambahkan fitur yang benar-benar diperlukan.

Ini bukanlah pustaka yang diimplementasikan setelah merancang daftar fitur terlebih dahulu. Kami menambahkan fungsi pencarian karena diperlukan dalam proyek operasional, menambahkan fungsi upsert dan bulk, serta menambahkan Atlas Search dan Vector Search untuk fungsi pencarian.

Kami mengutamakan produktivitas daripada kesempurnaan struktural.

Kami tidak mengklaim bahwa kelas inti yang besar adalah struktur yang ideal. Pada awalnya, lebih penting bagi tim untuk menangani pekerjaan MongoDB yang tidak familiar dengan cara yang sama dan cepat, dan kami masih mengutamakan alur penggunaan nyata daripada abstraksi itu sendiri.

Kami tidak membuat ulang apa yang sudah dilakukan oleh Driver.

Jika MongoDB Java Driver memiliki typed builder, kami akan menggunakan tipe tersebut sebisa mungkin. Kombinasi berulang yang dapat dikurangi dengan berharga oleh DSL disediakan sebagai convenience API, tetapi kami tidak menduplikasi Driver API dengan hanya mengganti namanya.

Harus bisa turun ke API dasar.

Kami tidak berpikir bahwa DSL dapat menggantikan semua situasi. Kami menyediakan escape hatch seperti Bson, filter/sort/operator/options Driver, dan publisher customizer, sehingga jika perlu, Anda dapat menggunakan MongoDB Driver secara langsung.

Empat alur yang dibahas dalam dokumen ini.

Query Mongo Umum.

Ini adalah alur di mana pustaka ini dimulai. Kami menyusun kondisi dan eksekusi dalam urutan execute* → fields(...) → end() → find/findAll/count/delete/exists/atomicUpdate.

Agregasi native Driver.

Jika Anda perlu mengontrol langsung dari stage pertama pipeline atau menggunakan fungsi agregasi baru yang disediakan oleh Driver, gunakan alur aggregation().stage(Bson). DSL dapat meneruskan stage yang sudah disediakan oleh Driver seperti $score, $scoreFusion tanpa mengimplementasikannya kembali.

Atlas Search

Ini adalah alur yang ditambahkan saat menerapkan Atlas Search ke proyek tanpa terlebih dahulu memperkenalkan layanan pencarian terpisah. Kami menyusun text, compound, score, highlight, dan sequence token setelah search(index).

Pencarian Vektor

Ini adalah alur yang ditambahkan untuk menghubungkan pencarian embedding di dalam MongoDB. Kami menyusun query vector atau automated embedding, ANN/ENN, pre/post filter, dan opsi nested/array embedding.

Model eksekusi 1.0.0.
text

Memisahkan query umum dan Search/Vector adalah untuk tidak menyembunyikan batasan pipeline nyata MongoDB. $search dan $vectorSearch memiliki batasan pada stage pertama, dan fungsi yang harus dikendalikan sepenuhnya oleh pemanggil dapat diturunkan ke aggregation().

Ruang lingkup yang digunakan dalam proyek nyata

Mengirim pasangan tanpa kondisi sebagai null untuk merakit kondisi pencarian dinamis berdasarkan layar.

Dengan PageStream, kami memisahkan data dan totalCount untuk menjaga alur pemrosesan besar dalam status penerbit reaktif.

Kami membuat pekerjaan yang aman dari eksekusi duplikat dengan atomicUpdate().upsertOne().document().setOnInsert(...).

Menyimpan data yang dikumpulkan dan data integrasi eksternal dengan bulk upsert berdasarkan ID atau kunci pekerjaan.

Mengembalikan hasil lookup dan total jumlah dalam satu pipeline dengan executeLookupAndCount.

Menggunakan sequence token dari Atlas Search dan query embedding otomatis dari Vector Search.

Stage agregasi baru yang disediakan oleh Driver terhubung langsung dengan aggregation().stage(Bson) atau stage(Bson) dari Search/Vector.

Jika diperlukan atomisitas antara operasi DSL, tentukan rentang transaksi ClientSession dengan getTxJob(...).

© 2026 Byeolnaerim. Semua hak dilindungi.PengenalanKebijakan Penanganan Data Pribadi