MongoDB este, fără îndoială, una dintre cele mai populare alegeri de baze de date NoSQL de astăzi. Și are o comunitate și un ecosistem extraordinar.

În acest articol, vom examina câteva dintre cele mai bune practici de urmat atunci când configurați MongoDB și Mongoose cu Node.js.

Cerințe preliminare pentru acest articol

Acest articol face parte din codedamn’s cale de învățare backend, de unde pornim de la elementele de bază ale backend-ului și le acoperim în detaliu. Prin urmare, presupun că aveți deja o anumită experiență cu JavaScript (și Node.js).

În prezent suntem aici:

Cum se utilizeaza MongoDB Mongoose cu Nodejs Cele

Dacă aveți foarte puțină experiență cu Node.js / JavaScript sau back-end-ul în general, acesta este probabil un loc bun pentru a începe. Puteți găsi, de asemenea, un curs gratuit pe Mongoose + MongoDB + Node.js aici. Hai să ne scufundăm.

De ce ai nevoie de Mangustă?

Pentru a înțelege de ce avem nevoie de Mongoose, să înțelegem cum funcționează MongoDB (și o bază de date) la nivel de arhitectură.

  • Aveți un server de baze de date (de exemplu, serverul comunității MongoDB)
  • Aveți un script Node.js care rulează (ca proces)

Serverul MongoDB ascultă pe un socket TCP (de obicei), iar procesul dvs. Node.js se poate conecta la acesta utilizând o conexiune TCP.

Dar pe partea de sus a TCP, MongoDB are și propriul său protocol pentru a înțelege ce anume vrea clientul (procesul nostru Node.js) să facă baza de date.

Pentru această comunicare, în loc să învățăm mesajele pe care trebuie să le trimitem pe stratul TCP, abstractizăm acest lucru cu ajutorul unui software „driver”, numit în acest caz driver MongoDB. Driverul MongoDB este disponibil ca pachet npm aici.

Acum, amintiți-vă, driverul MongoDB este responsabil pentru conectarea și abstractizarea solicitării / răspunsurilor de comunicare de la nivel scăzut de la dvs. – dar acest lucru vă ajută doar ca dezvoltator.

Deoarece MongoDB este o bază de date fără schemă, vă oferă mult mai multă putere decât aveți nevoie ca începător. Mai multă putere înseamnă mai multă suprafață pentru a greși lucrurile. Trebuie să vă reduceți suprafața de erori și înșurubări pe care le puteți face în codul dvs. Ai nevoie de ceva mai mult.

Faceți cunoștință cu Mangosta. Mongoose este o abstracție asupra driverului nativ MongoDB (pachetul npm pe care l-am menționat mai sus).

Regula generală cu abstracții (modul în care înțeleg) este că, la fiecare abstractizare, pierdeți o putere de funcționare la nivel scăzut. Dar asta nu înseamnă neapărat că este rău. Uneori crește productivitatea de 1000x +, deoarece niciodată nu trebuie să aveți acces complet la API-ul de bază.

O modalitate bună de a te gândi la asta este să creezi tehnic o aplicație de chat în timp real atât în ​​C, cât și în Python.

Exemplul Python ar fi mult mai ușor și mai rapid pentru dvs. ca dezvoltator de implementat cu o productivitate mai mare.

C ar putea să fie mai eficient, dar va avea un cost imens în productivitate / viteză de dezvoltare / bug-uri / blocări. În plus, în cea mai mare parte nu este nevoie să aveți puterea C pe care o oferă pentru a implementa websockets.

În mod similar, cu Mongoose, vă puteți limita suprafața de acces API de nivel inferior, dar puteți debloca o mulțime de câștiguri potențiale și un DX bun.

Cum se conectează Mongoose + MongoDB

În primul rând, să vedem rapid cum ar trebui să vă conectați la baza de date MongoDB în 2020 cu Mongoose:

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

Acest format de conexiune vă asigură că utilizați noul analizor URL de la Mongoose și că nu utilizați practici învechite. Puteți citi în detaliu despre toate aceste mesaje de depreciere aici dacă vrei.

Cum se efectuează operațiuni de mangustă

Să continuăm acum și să discutăm rapid operațiunile cu Mongoose și cum ar trebui să le efectuați.

Mangusta vă oferă opțiuni pentru două lucruri:

  1. Interogare bazată pe cursor
  2. Interogare completă

Interogare bazată pe cursor

Interogarea bazată pe cursor înseamnă că lucrați cu o singură înregistrare la un moment dat în timp ce preluați un singur sau un lot de documente la un moment dat din baza de date. Acesta este un mod eficient de a lucra cu cantități uriașe de date într-un mediu de memorie limitat.

Imaginați-vă că trebuie să analizați documente de 10 GB în dimensiune totală pe un server cloud de 1 GB / 1 core. Nu puteți prelua întreaga colecție, deoarece aceasta nu se va potrivi cu sistemul dvs. Cursorul este o opțiune bună (și singura?) Aici.

Interogare completă

Acesta este tipul de interogare în care obțineți răspunsul complet al interogării simultan. În cea mai mare parte, aceasta este ceea ce veți folosi. Prin urmare, ne vom concentra mai ales pe această metodă aici.

Cum se utilizează modelele Mongoose

Modelele sunt superputerea Mangustă. Acestea vă ajută să aplicați regulile „schemei” și vă oferă o integrare perfectă a codului dvs. Node în apelurile bazei de date.

Primul pas este de a defini un model bun:

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

Acesta este un exemplu redus direct din baza de coduri a codedamn. Câteva lucruri interesante pe care ar trebui să le rețineți aici:

  1. Încearcă să păstrezi required: true pe toate câmpurile necesare. Acest lucru vă poate ajuta să economisiți durerea dacă nu utilizați un sistem static de verificare a tipului precum TypeScript pentru a vă ajuta cu numele de proprietăți corecte în timp ce creați un obiect. În plus, validarea gratuită este și super tare.
  2. Definiți indexuri și câmpuri unice. unique proprietatea poate fi adăugată și într-o schemă. Indexurile sunt un subiect larg, așa că nu voi aprofunda aici. Dar pe o scară largă, ele vă pot ajuta cu adevărat să vă accelerați mult interogările.
  3. Definiți în mod explicit un nume de colecție. Deși Mongoose poate da automat un nume de colecție bazat pe numele modelului (Completed aici, de exemplu), aceasta este mult prea multă abstractizare în opinia mea. Ar trebui cel puțin să știți despre numele bazei de date și despre colecțiile din baza de cod.
  4. Restricționați valorile dacă puteți, folosind enumerări.

Cum se efectuează operațiuni CRUD

CRUD înseamnă Cculege, Read, Update și Delete. Acestea sunt cele patru opțiuni fundamentale cu care puteți efectua orice fel de manipulare a datelor într-o bază de date. Să vedem rapid câteva exemple ale acestor operațiuni.

Operațiunea de creare

Aceasta înseamnă pur și simplu crearea unei noi înregistrări într-o bază de date. Să folosim modelul pe care l-am definit mai sus pentru a crea o înregistrare:

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

Din nou, câteva indicii aici:

  1. Utilizați async-await în loc de apeluri de apel (frumos la ochi, fără un avantaj de performanță revoluționar ca atare)
  2. Utilizați blocuri try-catch în jurul interogărilor, deoarece interogarea dvs. poate sa eșec din mai multe motive (înregistrare duplicat, valoare incorectă și așa mai departe)

Operațiunea de citire

Aceasta înseamnă citirea valorilor existente din baza de date. este simplu, așa cum sună, dar există câteva gotchas pe care ar trebui să le cunoașteți cu Mongoose:

const res = await CompletedSchema.find(info).lean()
  1. Poți vedea lean() funcția sună acolo? Este foarte util pentru performanță. În mod implicit, Mongoose procesează documentele returnate din baza de date și le adaugă magic metodele de pe acesta (de exemplu .save)
  2. Când folosești .lean(), Mongoose returnează obiecte JSON simple în loc de documente grele de memorie și resurse. De asemenea, face interogările mai rapide și mai puțin costisitoare pe CPU.
  3. Cu toate acestea, puteți omite .lean() dacă de fapt vă gândiți să actualizați datele (vom vedea asta în continuare)

Operațiunea de actualizare

Dacă aveți deja la dumneavoastră un document Mongoose (fără a trage cu .lean()), puteți continua să modificați proprietatea obiectului și să o salvați folosind object.save():

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

Amintiți-vă că aici există două apeluri de baze de date efectuate. Primul este activat findOne iar al doilea este pornit doc.save.

Dacă puteți, trebuie să reduceți întotdeauna numărul de solicitări care ajung la baza de date (deoarece, dacă comparați memoria, rețeaua și discul, rețeaua este aproape întotdeauna cea mai lentă).

În celălalt caz, puteți utiliza o interogare ca aceasta:

const res = await CompletedSchema.updateOne(<condition>, <query>).lean()

și va efectua un singur apel către baza de date.

Operațiunea de ștergere

Ștergerea este, de asemenea, simplă cu Mongoose. Să vedem cum puteți șterge un singur document:

const res = await CompletedSchema.deleteOne(<condition>)

La fel ca updateOne, deleteOne acceptă, de asemenea, primul argument ca condiție de potrivire pentru document.

Există, de asemenea, o altă metodă numită deleteMany care ar trebui utilizat numai atunci când știți că doriți să ștergeți mai multe documente.

În orice alt caz, utilizați întotdeauna deleteOne pentru a evita ștergerile multiple accidentale, mai ales atunci când încercați să executați singuri interogări.

Concluzie

Acest articol a fost o simplă introducere în lumea Mongoose și MongoDB pentru dezvoltatorii Node.js.

Dacă ți-a plăcut acest articol, îți poți intensifica jocul și mai mult ca dezvoltator, urmând codedamn backend cale de învățare. Vă rog să nu ezitați să mă contactați mai departe Stare de nervozitate pentru orice feedback!