Cara Menggunakan MongoDB + Mongoose dengan Node.js - Amalan Terbaik untuk Dev Back Back

MongoDB tidak diragukan lagi adalah salah satu pilihan pangkalan data NoSQL yang paling popular hari ini. Dan ia mempunyai komuniti dan ekosistem yang hebat.

Dalam artikel ini, kami akan mengkaji beberapa amalan terbaik yang harus diikuti semasa anda menyiapkan MongoDB dan Mongoose dengan Node.js.

Prasyarat untuk artikel ini

Artikel ini adalah salah satu bahagian pembelajaran backend codedamn, di mana kita bermula dari asas backend dan membahasnya secara terperinci. Oleh itu, saya menganggap anda sudah mempunyai pengalaman dengan JavaScript (dan Node.js).

Pada masa ini kami di sini:

Sekiranya anda mempunyai sedikit pengalaman dengan Node.js / JavaScript atau bahagian belakang secara umum, ini mungkin merupakan tempat yang baik untuk memulakan. Anda juga boleh mendapatkan kursus percuma di Mongoose + MongoDB + Node.js di sini. Mari selami.

Mengapa anda memerlukan Mongoose?

Untuk memahami mengapa kita memerlukan Mongoose, mari kita fahami bagaimana MongoDB (dan pangkalan data) berfungsi pada tahap seni bina.

  • Anda mempunyai pelayan pangkalan data (misalnya, pelayan komuniti MongoDB)
  • Anda mempunyai skrip Node.js berjalan (sebagai proses)

Pelayan MongoDB mendengar pada soket TCP (biasanya), dan proses Node.js anda dapat menyambung ke dalamnya menggunakan sambungan TCP.

Tetapi di bahagian atas TCP, MongoDB juga mempunyai protokolnya sendiri untuk memahami apa sebenarnya yang dikehendaki oleh klien (proses Node.js kami) pangkalan data.

Untuk komunikasi ini, alih-alih mempelajari mesej yang harus kita kirimkan pada lapisan TCP, kita membuangnya dengan bantuan perisian "pemacu", yang disebut pemacu MongoDB dalam kes ini. Pemandu MongoDB boleh didapati sebagai pakej npm di sini.

Sekarang ingat, pemacu MongoDB bertanggungjawab untuk menghubungkan dan mengaburkan permintaan / respons komunikasi peringkat rendah daripada anda - tetapi ini hanya menjadikan anda sebagai pembangun.

Oleh kerana MongoDB adalah pangkalan data tanpa skema, ia memberi anda lebih banyak kekuatan daripada yang anda perlukan sebagai pemula. Lebih banyak kuasa bermaksud lebih banyak luas permukaan untuk membuat kesilapan. Anda perlu mengurangkan kawasan permukaan bug dan skru yang boleh anda buat dalam kod anda. Anda memerlukan sesuatu yang lebih.

Jumpa Mongoose. Mongoose adalah pengabaian terhadap pemacu MongoDB asli (pakej npm yang saya nyatakan di atas).

Peraturan umum dengan abstraksi (seperti yang saya fahami) adalah bahawa dengan setiap abstraksi, anda kehilangan daya operasi tahap rendah. Tetapi itu tidak semestinya itu buruk. Kadang-kadang ia meningkatkan produktiviti 1000x + kerana anda tidak perlu mempunyai akses penuh ke API yang mendasari.

Kaedah yang baik untuk memikirkannya adalah secara teknikal anda membuat aplikasi sembang masa nyata di C dan Python.

Contoh Python akan menjadi lebih mudah dan pantas bagi anda sebagai pembangun untuk dilaksanakan dengan produktiviti yang lebih tinggi.

C mungkin lebih cekap, tetapi akan menghasilkan kos yang besar dalam produktiviti / kelajuan pengembangan / bug / kerosakan. Plus, untuk sebahagian besar anda tidak perlu memiliki kekuatan C memberi anda untuk menerapkan soket web.

Begitu juga dengan Mongoose, anda boleh mengehadkan kawasan permukaan anda dengan akses API tahap rendah, tetapi membuka banyak potensi keuntungan dan DX yang baik.

Cara menghubungkan Mongoose + MongoDB

Pertama, mari kita lihat dengan cepat bagaimana anda harus menyambung ke pangkalan data MongoDB anda pada tahun 2020 dengan Mongoose:

mongoose.connect(DB_CONNECTION_STRING, { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true, useFindAndModify: false })

Format sambungan ini memastikan bahawa anda menggunakan Parser URL baru dari Mongoose, dan bahawa anda tidak menggunakan amalan yang tidak digunakan lagi. Anda boleh membaca dengan lebih mendalam mengenai semua mesej penghentian ini di sini jika anda mahu.

Cara melakukan operasi Mongoose

Mari kita teruskan dan cepat membincangkan operasi dengan Mongoose, dan bagaimana anda harus melaksanakannya.

Mongoose memberi anda pilihan untuk dua perkara:

  1. Pertanyaan berdasarkan kursor
  2. Pertanyaan pengambilan penuh

Pertanyaan berdasarkan kursor

Pertanyaan berdasarkan kursor bermaksud bahawa anda bekerja dengan satu rekod pada satu masa semasa anda mengambil satu atau sekumpulan dokumen sekaligus dari pangkalan data. Ini adalah cara yang berkesan untuk bekerja dengan sejumlah besar data dalam persekitaran memori yang terhad.

Bayangkan bahawa anda harus menghuraikan dokumen bersaiz 10GB pada pelayan awan 1GB / 1core. Anda tidak dapat mengambil keseluruhan koleksi kerana tidak akan sesuai dengan sistem anda. Kursor adalah pilihan yang baik (dan satu-satunya?) Di sini.

Pertanyaan pengambilan penuh

Ini adalah jenis pertanyaan di mana anda mendapat respons penuh pertanyaan anda sekaligus. Sebahagian besarnya, inilah yang akan anda gunakan. Oleh itu, kami akan memfokuskan kebanyakan kaedah ini di sini.

Cara menggunakan Model Mongoose

Model adalah kuasa besar Mongoose. Mereka membantu anda menguatkuasakan peraturan "skema" dan menyediakan penyatuan kod Node anda dengan lancar ke dalam panggilan pangkalan data.

Langkah pertama adalah menentukan model yang baik:

import mongoose from 'mongoose' const CompletedSchema = new mongoose.Schema( { type: { type: String, enum: ['course', 'classroom'], required: true }, parentslug: { type: String, required: true }, slug: { type: String, required: true }, userid: { type: String, required: true } }, { collection: 'completed' } ) CompletedSchema.index({ slug: 1, userid: 1 }, { unique: true }) const model = mongoose.model('Completed', CompletedSchema) export default model 

Ini adalah salah satu contoh yang dipotong terus dari pangkalan data codedamn. Beberapa perkara menarik yang harus anda perhatikan di sini:

  1. Cuba teruskan required: truesemua bidang yang diperlukan. Ini boleh menjadi penghilang rasa sakit yang besar bagi anda jika anda tidak menggunakan sistem pemeriksaan jenis statik seperti TypeScript untuk membantu anda dengan nama harta yang betul semasa membuat objek. Tambahan pengesahan percuma juga hebat.
  2. Tentukan indeks dan bidang unik. uniqueharta benda juga boleh ditambahkan dalam skema. Indeks adalah topik yang luas, jadi saya tidak akan membahasnya secara mendalam di sini. Tetapi dalam skala besar, mereka benar-benar dapat membantu anda mempercepat pertanyaan anda.
  3. Define a collection name explicitly. Although Mongoose can automatically give a collection name based on the name of model (Completed here, for example), this is way too much abstraction in my opinion. You should at least know about your database names and collections in your codebase.
  4. Restrict values if you can, using enums.

How to perform CRUD Operations

CRUD means Create, Read, Update and Delete. These are the four fundamental options with which you can perform any sort of data manipulation in a database. Let's quickly see some examples of these operations.

The Create Operation

This simply means creating a new record in a database. Let's use the model we defined above to create a record:

try { const res = await CompletedSchema.create(record) } catch(error) { console.error(error) // handle the error }

Again, a few pointers here:

  1. Use async-await instead of callbacks (nice on the eyes, no ground breaking performance benefit as such)
  2. Use try-catch blocks around queries because your query can fail for a number of reasons (duplicate record, incorrect value, and so on)

The Read Operation

This means reading existing values from the database. it's simple just like it sounds, but there are a couple of gotchas you should know with Mongoose:

const res = await CompletedSchema.find(info).lean()
  1. Can you see the lean() function call there? It is super useful for performance. By default, Mongoose processes the returned document(s) from the database and adds its magical methods on it (for example .save)
  2. When you use .lean(), Mongoose returns plain JSON objects instead of memory and resource heavy documents. Makes queries faster and less expensive on your CPU, too.
  3. However, you can omit .lean() if you are actually thinking of updating data (we'll see that next)

The Update Operation

If you already have a Mongoose document with you (without firing with .lean()), you can simply go ahead and modify the object property, and save it using object.save():

const doc = await CompletedSchema.findOne(info) doc.slug = 'something-else' await doc.save()

Remember that here, there are two database calls made. The first one is on findOne and the second one is on doc.save.

If you can, you should always reduce the number of requests hitting the database (because if you're comparing memory, network, and disk, network is almost always the slowest).

In the other case, you can use a query like this:

const res = await CompletedSchema.updateOne(, ).lean()

and it will only make a single call to the database.

The Delete Operation

Delete is also straightforward with Mongoose. Let's see how you can delete a single document:

const res = await CompletedSchema.deleteOne()

Just like updateOne, deleteOne also accepts the first argument as the matching condition for the document.

There is also another method called deleteMany which should be used only when you know you want to delete multiple documents.

In any other case, always use deleteOne to avoid accidental multiple deletes, especially when you're trying to execute queries yourself.

Conclusion

This article was a simple introduction to the Mongoose and MongoDB world for Node.js developers.

If you enjoyed this article, you can step up your game even more as a developer by following the codedamn backend learning path. Please feel free to reach out to me on Twitter for any feedback!