door Nick Karnik
Mongoose is een object Data Modeling (ODM) bibliotheek voor MongoDB en Node.js. Het beheert relaties tussen gegevens, biedt schemavalidatie en wordt gebruikt om te vertalen tussen objecten in code en de representatie van die objecten in MongoDB.
MongoDB is een Schemaloze NoSQL-documentdatabase., Het betekent dat u JSON-documenten erin kunt opslaan, en de structuur van deze documenten kan variëren omdat het niet wordt afgedwongen zoals SQL-databases. Dit is een van de voordelen van het gebruik van NoSQL, omdat het de ontwikkeling van applicaties versnelt en de complexiteit van implementaties vermindert.
Hieronder is een voorbeeld van hoe gegevens worden opgeslagen in Mongo vs. SQL Database:
terminologieën
collecties
‘collecties’ in Mongo zijn gelijk aan tabellen in relationele databases. Ze kunnen meerdere JSON documenten bevatten.
documenten
“documenten” zijn gelijkwaardig aan records of rijen met gegevens in SQL. Terwijl een SQL-rij gegevens in andere tabellen kan verwijzen, combineren Mongo-documenten dat meestal in een document.
velden
‘velden’ of attributen zijn vergelijkbaar met kolommen in een SQL-tabel.
Schema
terwijl Mongo schemaloos is, definieert SQL een schema via de tabeldefinitie., Een Mongoose ‘schema’ is een document datastructuur (of vorm van het document) die wordt afgedwongen via de applicatielaag.
modellen
‘modellen’ zijn constructeurs met een hogere orde die een schema nemen en een exemplaar maken van een document dat gelijkwaardig is aan records in een relationele database.
aan de slag
Mongo installatie
voordat we beginnen, laten we Mongo instellen., U kunt kiezen uit een van de volgende opties (we gebruiken Optie #1 voor dit artikel):
- Download de juiste MongoDB-versie voor uw besturingssysteem van de MongoDB-Website en volg hun installatie-instructies
- Maak een gratis sandbox-database-abonnement op mLab
- Install Mongo using Docker Als u liever docker
gebruikt laten we door enkele basisprincipes van Mongoose navigeren door een model te implementeren dat gegevens vertegenwoordigt voor een vereenvoudigd adresboek.
Ik gebruik Visual Studio Code, Node 8.9, en NPM 5.6., Start je favoriete IDE, Maak een leeg project, en laten we beginnen! We zullen de beperkte ES6 syntaxis in Node gebruiken, dus we zullen Babel niet configureren.
npm Install
laten we naar de projectmap gaan en ons project initialiseren
npm init -y
laten we Mongoose en een validatiebibliotheek installeren met het volgende commando:
npm install mongoose validator
het bovenstaande commando installeert de nieuwste versie van de bibliotheken. De Mongoose syntaxis in dit artikel is specifiek voor Mongoose v5 en verder.,
databaseverbinding
Maak een bestand ./src/database.js
onder de Project root.
vervolgens zullen we een eenvoudige klasse toevoegen met een methode die verbinding maakt met de database.
uw verbindingsreeks zal variëren afhankelijk van uw installatie.
de require(‘mongoose’)
aanroep hierboven geeft een Singleton-object terug. Het betekent dat de eerste keer dat je require(‘mongoose’)
aanroept, het een instantie van de Mongoose klasse aanmaakt en het retourneert., Bij volgende oproepen, zal het dezelfde instantie die is gemaakt en teruggestuurd naar u de eerste keer als gevolg van hoe module import/export werkt in ES6 retourneren.
evenzo hebben we onze Databaseklasse veranderd in een singleton door een instantie van de klasse in het module.exports
te retourneren omdat we slechts één verbinding met de database nodig hebben.,
ES6 maakt het heel gemakkelijk voor ons om een singleton (single instance) patroon te maken vanwege hoe de module loader werkt door het cachen van de respons van een eerder geïmporteerd bestand.
Mongoosschema vs. Model
een Mongoosmodel is een wrapper op het mongoosschema. Een Mongoose schema definieert de structuur van het document, standaardwaarden, validators, enz., terwijl een Mongoose-model een interface aan het gegevensbestand verstrekt voor het creëren, het opvragen, het bijwerken, het verwijderen van verslagen, enz.
Het creëren van een Mongoosmodel bestaat voornamelijk uit drie delen:
1., Referencing Mongoose
let mongoose = require('mongoose')
deze referentie zal dezelfde zijn als degene die werd geretourneerd toen we verbinding maakten met de database, wat betekent dat de schema-en modeldefinities niet expliciet verbinding hoeven te maken met de database.
2. Schema
een schema definieert Documenteigenschappen via een object waarbij de sleutelnaam overeenkomt met de eigenschapsnaam in de collectie.,
let emailSchema = new mongoose.Schema({ email: String})
hier definiëren we een eigenschap genaamd e-mail met een schema Type String die toewijst aan een interne validator die zal worden geactiveerd wanneer het model wordt opgeslagen in de database. Het zal mislukken als het gegevenstype van de waarde geen stringtype is.
De volgende Schematypen zijn toegestaan:
- Array
- Boolean
- Buffer
- Datum
- gemengd (een generiek / flexibel gegevenstype)
- nummer
- ObjectId
- String
gemengd en ObjectId zijn gedefinieerd onder require(‘mongoose’).Schema.Types
.
3., Exporteren van een Model
We moeten de modelbouwer op de Mongoose instantie aanroepen en het de naam van de collectie en een verwijzing naar de schemadefinitie doorgeven.
module.exports = mongoose.model('Email', emailSchema)
laten we de bovenstaande code combineren in ./src/models/email.js
om de inhoud van een basis E-mailmodel te definiëren:
een schemadefinitie zou eenvoudig moeten zijn, maar de complexiteit ervan is meestal gebaseerd op toepassingseisen. Schema ’s kunnen worden hergebruikt en ze kunnen ook meerdere child-schema’ s bevatten. In het bovenstaande voorbeeld is de waarde van de e-maileigenschap een eenvoudig waardetype., Het kan echter ook een objecttype zijn met extra eigenschappen erop.
We kunnen een exemplaar van het hierboven gedefinieerde model maken en het vullen met de volgende syntaxis:
let EmailModel = require('./email')let msg = new EmailModel({ email: '[email protected]'})
laten we het e-mailschema verbeteren om de e-maileigenschap een uniek, verplicht veld te maken en de waarde naar kleine letters converteren voordat we het opslaan. We kunnen ook een validatiefunctie toevoegen die ervoor zorgt dat de waarde Een geldig e-mailadres is. We zullen verwijzen naar en gebruik maken van de validator bibliotheek eerder geïnstalleerd.,
basisbewerkingen
Mongoose heeft een flexibele API en biedt vele manieren om een taak uit te voeren. We zullen ons niet richten op de variaties omdat dat buiten het bereik van dit artikel valt, maar vergeet niet dat de meeste bewerkingen op meer dan één manier syntactisch of via de applicatiearchitectuur kunnen worden uitgevoerd.,
Record Maken
Laten we het maken van een exemplaar van het e-model en het opslaan in de database:
Het resultaat is een document dat wordt teruggegeven bij een succesvolle opslaan:
{ _id: 5a78fe3e2f44ba8f85a2409a, email: '[email protected]', __v: 0 }
De volgende velden worden geretourneerd (interne velden worden aangeduid met een underscore):
- De
_id
veld is automatisch gegenereerd door Mongo en is een primaire sleutel van de collectie. De waarde is een unieke identificatie voor het document. - de waarde van het veld
email
wordt geretourneerd., Merk op dat het minder-cased is omdat we hetlowercase:true
attribuut in het schema hebben opgegeven. -
__v
is de versionKey-eigenschap die op elk document wordt ingesteld wanneer deze voor het eerst door Mongoose wordt aangemaakt. De waarde ervan omvat de interne herziening van het document.
als u probeert de bewaarbewerking hierboven te herhalen, krijgt u een fout omdat we hebben opgegeven dat het e-mailveld uniek moet zijn.
Record ophalen
laten we proberen de record die we eerder in de database hebben opgeslagen op te halen., De modelklasse toont verschillende statische en instance methoden om bewerkingen uit te voeren op de database. We zullen nu proberen om het record dat we eerder hebben gemaakt met behulp van de zoekmethode te vinden en geef de e-mail als de zoekterm.
EmailModel .find({ email: '[email protected]' // search query }) .then(doc => { console.log(doc) }) .catch(err => { console.error(err) })
het geretourneerde document zal vergelijkbaar zijn met wat werd weergegeven toen we het record maakten:
{ _id: 5a78fe3e2f44ba8f85a2409a, email: '[email protected]', __v: 0 }
update Record
laten we het record hierboven wijzigen door het e-mailadres te wijzigen en er een ander veld aan toe te voegen, allemaal in een enkele bewerking., Om redenen van prestatie zal Mongoose het bijgewerkte document niet retourneren, dus moeten we een extra parameter doorgeven om ernaar te vragen:
het geretourneerde document bevat de bijgewerkte e-mail:
{ _id: 5a78fe3e2f44ba8f85a2409a, email: '[email protected]', __v: 0 }
Verwijder Record
We zullen de findOneAndRemove
aanroep gebruiken om een record te verwijderen., Het retourneert het originele document dat werd verwijderd:
Helpers
we hebben gekeken naar een aantal van de basisfunctionaliteit hierboven bekend als CRUD (Create, Read, Update, Delete) operaties, maar Mongoose biedt ook de mogelijkheid om verschillende soorten helper methoden en eigenschappen te configureren. Deze kunnen worden gebruikt om het werken met gegevens verder te vereenvoudigen.
laten we een gebruikersschema maken in ./src/models/user.js
met de veldenfirstName
en lastName
:
virtuele eigenschap
een virtuele eigenschap wordt niet aan de database gekoppeld., We kunnen het toevoegen aan ons schema als hulp om waarden te krijgen en in te stellen.
laten we een virtuele eigenschap maken genaamd fullName
die kan worden gebruikt om waarden in te stellen op firstName
en lastName
en ze ophalen als een gecombineerde waarde bij het lezen:
Callbacks voor get en set moeten het functietoetswoord gebruiken omdat we toegang moeten krijgen tot het model via de this
trefwoord. Het gebruik van Fat arrow functies zal veranderen waar this
naar verwijst.,
nu kunnen we firstName
en lastName
instellen door een waarde toe te kennen aan fullName
:
de bovenstaande code zal het volgende uitvoeren:
{ _id: 5a7a4248550ebb9fafd898cf, firstName: 'Thomas', lastName: 'Anderson' } Thomas Anderson
Instance Methods
We kunnen aangepaste helper methoden maken op het schema en ze benaderen via het model instance. Deze methoden zullen toegang hebben tot het modelobject en ze kunnen heel creatief worden gebruikt. We kunnen bijvoorbeeld een methode maken om alle mensen te vinden die dezelfde voornaam hebben als de huidige instantie.,
in dit voorbeeld maken we een functie om de initialen voor de huidige gebruiker terug te geven. Laten we een aangepaste helper methode genaamd getInitials
toevoegen aan het schema:
userSchema.methods.getInitials = function() { return this.firstName + this.lastName}
deze methode zal toegankelijk zijn via een model instantie:
statische methoden
vergelijkbaar met instance methoden, kunnen we statische methoden maken op het schema., Laten we een methode maken om alle gebruikers in de database op te halen:
het aanroepen van getUsers
op de modelklasse geeft alle gebruikers in de database terug:
UserModel.getUsers() .then(docs => { console.log(docs) }) .catch(err => { console.error(err) })
het toevoegen van instance en statische methoden is een mooie aanpak om een interface te implementeren voor database interacties op collecties en records.
Middleware
Middleware zijn functies die draaien in specifieke stadia van een pijplijn., Mongoose ondersteunt middleware voor de volgende activiteiten:
- Geaggregeerde
- Document
- Model
- Query
bijvoorbeeld, modellen pre
en post
functies die twee parameters:
- Type gebeurtenis (‘init’, ‘controleren’, ‘opslaan’, ‘verwijderen’)
- Een callback die is uitgevoerd met deze verwijzen naar het model instance
laten we een voorbeeld proberen door twee velden genaamd createdAt
en updatedAt
aan ons schema toe te voegen:
wanneer model.save()
wordt aangeroepen, is er een pre(‘save’, …)
en post(‘save’, …)
gebeurtenis die wordt geactiveerd. Voor de tweede parameter kunt u een functie doorgeven die wordt aangeroepen wanneer de gebeurtenis wordt geactiveerd. Deze functies nemen een parameter mee naar de volgende functie in de middleware keten.,
laten we een pre-save hook toevoegen en waarden instellen voor createdAt
en updatedAt
:
laten we ons model aanmaken en opslaan:
u zou waarden moeten zien voor createdAt
en updatedAt
wanneer de gemaakte record wordt afgedrukt:
plugins
stel dat we willen bijhouden wanneer een record is gemaakt en voor het laatst bijgewerkt op elke verzameling in onze database. In plaats van het bovenstaande proces te herhalen, kunnen we een plugin maken en toepassen op elk schema.,
laten we een bestand maken ./src/model/plugins/timestamp.js
en de bovenstaande functionaliteit repliceren als een herbruikbare module:
om deze plugin te gebruiken, geven we het gewoon door aan de schema ‘ s die deze functionaliteit moeten krijgen:
Query Building
Mongoose heeft een zeer rijke API die veel complexe operaties ondersteunt door MongoDB. Overweeg een query waar we kunnen stapsgewijs bouwen query componenten.,
In dit voorbeeld gaan we:
- alle gebruikers zoeken
- De eerste 100 records overslaan
- de resultaten beperken tot 10 records
- Sorteer de resultaten op het veld Voornaam
- selecteer de voornaam
- voer die query uit
Closing
We hebben nog maar net de mogelijkheden van Mongoose verkend. Het is een rijke bibliotheek vol met nuttige en krachtige functies die het een plezier maken om te werken met gegevensmodellen in de applicatielaag.,
hoewel u direct met Mongo kunt communiceren met behulp van Mongo Driver, zal Mongoose die interactie vereenvoudigen door u toe te staan relaties tussen gegevens te modelleren en ze gemakkelijk te valideren.
Fun Fact: Mongoose is gemaakt door Valeri Karpov die een ongelooflijk getalenteerde ingenieur is! Hij bedacht de term the MEAN Stack.