von Nick Karnik
Mongoose ist eine Objektdatenmodellierungsbibliothek (ODM) für MongoDB und Node.js. Es verwaltet Beziehungen zwischen Daten, bietet Schemaüberprüfung und wird verwendet, um zwischen Objekten im Code und der Darstellung dieser Objekte in MongoDB zu übersetzen.
MongoDB ist eine NoSQL-Dokumentdatenbank ohne Schema., Dies bedeutet, dass Sie JSON-Dokumente darin speichern können und die Struktur dieser Dokumente variieren kann, da sie nicht wie SQL-Datenbanken erzwungen wird. Dies ist einer der Vorteile der Verwendung von NoSQL, da es die Anwendungsentwicklung beschleunigt und die Komplexität von Bereitstellungen reduziert.
Unten finden Sie ein Beispiel dafür, wie Daten in der Mongo vs. SQL-Datenbank gespeichert werden:
Terminologien
Sammlungen
‚Sammlungen‘ in Mongo entsprechen Tabellen in relationalen Datenbanken. Sie können mehrere JSON-Dokumente.
Dokumente
‚Dokumente‘ entsprechen Datensätzen oder Datenzeilen in SQL. Während eine SQL-Zeile auf Daten in anderen Tabellen verweisen kann, kombinieren Mongo-Dokumente diese normalerweise in einem Dokument.
Felder
‚Felder‘ oder Attribute ähneln Spalten in einer SQL-Tabelle.
Schema
Während Mongo Schema-less ist, definiert SQL ein Schema über die Tabellendefinition., Ein mongooses ‚Schema‘ ist eine Dokumentdatenstruktur (oder Form des Dokuments), die über die Anwendungsschicht erzwungen wird.
Models
‚Models‘ sind Konstruktoren höherer Ordnung, die ein Schema verwenden und eine Instanz eines Dokuments erstellen, das Datensätzen in einer relationalen Datenbank entspricht.
Erste Schritte
Mongo Installation
Bevor wir loslegen, richten wir Mongo ein., Sie können aus einer der folgenden Optionen wählen (wir verwenden Option #1 für diesen Artikel):
- Laden Sie die entsprechende MongoDB-Version für Ihr Betriebssystem von der MongoDB-Website herunter und folgen Sie deren Installationsanweisungen
- Erstellen Sie ein kostenloses Sandbox-Datenbankabonnement auf mLab
- Installieren Sie Mongo mit Docker Wenn Sie docker
verwenden möchten, navigieren wir durch einige der Grundlagen von Mongoose, indem wir ein Modell implementieren, das Daten für ein vereinfachtes Adressbuch darstellt.
Ich verwende Visual Studio Code, Node 8.9 und NPM 5.6., Feuern Sie Ihre Lieblings-IDE, erstellen Sie ein leeres Projekt, und Los geht ‚ s! Wir werden die begrenzte ES6-Syntax in Node verwenden, damit wir Babel nicht konfigurieren.
NPM Install
Gehen wir zum Projektordner und initialisieren unser Projekt
npm init -y
Installieren wir Mongoose und eine Validierungsbibliothek mit dem folgenden Befehl:
npm install mongoose validator
Der obige Installationsbefehl installiert die neueste Version der Bibliotheken. Die Mongoose Syntax in diesem Artikel ist spezifisch für Mongoose v5 und darüber hinaus.,
Datenbankverbindung
Erstellen Sie eine Datei ./src/database.js
unter dem Projektstamm.
als Nächstes fügen wir eine einfache Klasse mit einer Methode, die eine Verbindung zur Datenbank herstellt.
Ihre Verbindungszeichenfolge variiert je nach Installation.
Der obige Aufruf require(‘mongoose’)
gibt ein Singleton-Objekt zurück. Dies bedeutet, dass beim ersten Aufruf von require(‘mongoose’)
eine Instanz der Mongoose-Klasse erstellt und zurückgegeben wird., Bei nachfolgenden Aufrufen wird dieselbe Instanz zurückgegeben, die beim ersten Mal erstellt und an Sie zurückgegeben wurde, da der Modulimport/ – export in ES6 funktioniert.
In ähnlicher Weise haben wir unsere Datenbankklasse in einen Singleton verwandelt, indem wir eine Instanz der Klasse in der module.exports
– Anweisung zurückgegeben haben, da wir nur eine einzige Verbindung zur Datenbank benötigen.,
ES6 macht es uns sehr einfach, ein Singleton-Muster (Single Instance) zu erstellen, da der Modullader die Antwort einer zuvor importierten Datei zwischenspeichert.
Mungo-Schema vs. Modell
Ein Mungo-Modell ist ein Wrapper für das Mungo-Schema. Ein Mongoose-Schema definiert die Struktur des Dokuments, Standardwerte,Validatoren usw., während ein Mungo-Modell eine Schnittstelle zur Datenbank zum Erstellen, Abfragen, Aktualisieren, Löschen von Datensätzen usw. bereitstellt.
Das Erstellen eines Mungo-Modells besteht hauptsächlich aus drei Teilen:
1., Referenzierung Mongoose
let mongoose = require('mongoose')
Diese Referenz entspricht der Referenz, die zurückgegeben wurde, als wir eine Verbindung zur Datenbank hergestellt haben, was bedeutet, dass die Schema-und Modelldefinitionen keine explizite Verbindung zur Datenbank herstellen müssen.
2. Definieren des Schemas
Ein Schema definiert Dokumenteigenschaften über ein Objekt, bei dem der Schlüsselname dem Eigenschaftsnamen in der Sammlung entspricht.,
let emailSchema = new mongoose.Schema({ email: String})
Hier definieren wir eine Eigenschaft namens email mit einer Schematypzeichenfolge, die einem internen Validator zugeordnet wird, der ausgelöst wird, wenn das Modell in der Datenbank gespeichert wird. Es schlägt fehl, wenn der Datentyp des Werts kein String-Typ ist.
Die folgenden Schematypen sind zulässig:
- Array
- Boolean
- Buffer
- Date
- Mixed (Ein generischer / flexibler Datentyp)
- Number
- ObjectId
- String
Mixed und ObjectId sind unter require(‘mongoose’).Schema.Types
.
3., Exportieren eines Modells
Wir müssen den Modellkonstruktor für die Mongoose-Instanz aufrufen und ihm den Namen der Sammlung und einen Verweis auf die Schemadefinition übergeben.
module.exports = mongoose.model('Email', emailSchema)
Kombinieren wir den obigen Code zu ./src/models/email.js
, um den Inhalt eines grundlegenden E-Mail-Modells zu definieren:
Eine Schemadefinition sollte einfach sein, aber ihre Komplexität basiert normalerweise auf den Anwendungsanforderungen. Schemas können wiederverwendet werden und sie können auch mehrere untergeordnete Schemas enthalten. Im obigen Beispiel ist der Wert der E-Mail-Eigenschaft ein einfacher Werttyp., Es kann sich jedoch auch um einen Objekttyp mit zusätzlichen Eigenschaften handeln.
Wir können eine Instanz des oben definierten Modells erstellen und mit der folgenden Syntax auffüllen:
let EmailModel = require('./email')let msg = new EmailModel({ email: '[email protected]'})
Erweitern wir das E-Mail-Schema, um die E-Mail-Eigenschaft zu einem eindeutigen erforderlichen Feld zu machen und den Wert vor dem Speichern in Kleinbuchstaben umzuwandeln. Wir können auch eine Validierungsfunktion hinzufügen, die sicherstellt, dass der Wert eine gültige E-Mail-Adresse ist. Wir werden auf die zuvor installierte Validator-Bibliothek verweisen und diese verwenden.,
Grundlegende Operationen
Mongoose verfügt über eine flexible API und bietet viele Möglichkeiten, eine Aufgabe zu erfüllen. Wir werden uns nicht auf die Variationen konzentrieren, da dies für diesen Artikel nicht möglich ist, aber denken Sie daran, dass die meisten Operationen auf mehr als eine Weise entweder syntaktisch oder über die Anwendungsarchitektur ausgeführt werden können.,
Datensatz erstellen
Erstellen Sie eine Instanz des E-Mail-Modells und speichern Sie sie in der Datenbank:
Das Ergebnis ist ein Dokument, das bei einem erfolgreichen Speichern zurückgegeben wird:
{ _id: 5a78fe3e2f44ba8f85a2409a, email: '[email protected]', __v: 0 }
Die folgenden Felder werden zurückgegeben (internen Feldern wird ein Unterstrich vorangestellt):
- Das Feld
_id
wird automatisch von Mongo generiert und ist ein Primärschlüssel der Sammlung. Sein Wert ist eine eindeutige Kennung für das Dokument. - Der Wert des Feldes
email
wird zurückgegeben., Beachten Sie, dass es sich um Kleinbuchstaben handelt, da wir das Attributlowercase:true
im Schema angegeben haben. -
__v
ist die versionKey-Eigenschaft, die bei der ersten Erstellung durch Mongoose für jedes Dokument festgelegt wurde. Sein Wert enthält die interne revision des Dokuments.
Wenn Sie versuchen, den obigen Speichervorgang zu wiederholen, wird eine Fehlermeldung angezeigt, da wir angegeben haben, dass das E-Mail-Feld eindeutig sein soll.
Datensatz abrufen
Versuchen wir, den zuvor in der Datenbank gespeicherten Datensatz abzurufen., Die Modellklasse stellt mehrere statische und Instanzmethoden bereit, um Vorgänge in der Datenbank auszuführen. Wir werden nun versuchen, den Datensatz zu finden, den wir zuvor mit der Suchmethode erstellt haben, und die E-Mail als Suchbegriff übergeben.
EmailModel .find({ email: '[email protected]' // search query }) .then(doc => { console.log(doc) }) .catch(err => { console.error(err) })
Das zurückgegebene Dokument ähnelt dem, was beim Erstellen des Datensatzes angezeigt wurde:
{ _id: 5a78fe3e2f44ba8f85a2409a, email: '[email protected]', __v: 0 }
Update Record
Ändern wir den obigen Datensatz, indem wir die E-Mail-Adresse ändern und ein weiteres Feld hinzufügen, alles in einem einzigen Vorgang., Aus Leistungsgründen gibt Mongoose das aktualisierte Dokument nicht zurück, daher müssen wir einen zusätzlichen Parameter übergeben, um danach zu fragen:
Das zurückgegebene Dokument enthält die aktualisierte E-Mail:
{ _id: 5a78fe3e2f44ba8f85a2409a, email: '[email protected]', __v: 0 }
Delete Record
Wir verwenden den Aufruf findOneAndRemove
, um einen Datensatz zu löschen., Es gibt das Originaldokument zurück, das entfernt wurde:
Helfer
Wir haben uns einige der oben genannten grundlegenden Funktionen angesehen, die als CRUD-Operationen (Erstellen, Lesen, Aktualisieren, Löschen) bezeichnet werden, aber Mongoose bietet auch die Möglichkeit, verschiedene Arten von Hilfsmethoden und-eigenschaften zu konfigurieren. Diese können verwendet werden, um die Arbeit mit Daten weiter zu vereinfachen.
Erstellen wir ein Benutzerschema in ./src/models/user.js
mit den FeldernfirstName
und lastName
:
Virtuelle Eigenschaft
Eine virtuelle Eigenschaft wird nicht in der Datenbank gespeichert., Wir können es unserem Schema als Helfer hinzufügen, um Werte abzurufen und festzulegen.
Erstellen wir eine virtuelle Eigenschaft mit dem Namen fullName
, mit der Werte für firstName
und lastName
festgelegt und beim Lesen als kombinierter Wert abgerufen werden können:
Rückrufe für get und set müssen das Funktionsschlüsselwort verwenden, da wir über die this
stichwort. Die Verwendung von Fat-Pfeilfunktionen ändert, worauf sich this
bezieht.,
Jetzt können wir firstName
und lastName
setzen, indem wir fullName
Der obige Code gibt Folgendes aus:
{ _id: 5a7a4248550ebb9fafd898cf, firstName: 'Thomas', lastName: 'Anderson' } Thomas Anderson
Instanzmethoden
Wir können benutzerdefinierte Hilfsmethoden auf der das Schema und greifen Sie über die Modellinstanz darauf zu. Diese Methoden haben Zugriff auf das Modellobjekt und können recht kreativ verwendet werden. Zum Beispiel könnten wir eine Methode erstellen, um alle Personen zu finden, die denselben Vornamen wie die aktuelle Instanz haben.,
In diesem Beispiel erstellen wir eine Funktion, um die Initialen für den aktuellen Benutzer zurückzugeben. Fügen wir dem Schema eine benutzerdefinierte Hilfsmethode namens getInitials
hinzu:
userSchema.methods.getInitials = function() { return this.firstName + this.lastName}
Auf diese Methode kann über eine Modellinstanz zugegriffen werden:
Statische Methoden
Ähnlich wie Instanzmethoden können wir statische Methoden für das Schema erstellen., Erstellen wir eine Methode zum Abrufen aller Benutzer in der Datenbank:
Wenn Sie getUsers
in der Modellklasse aufrufen, werden alle Benutzer in der Datenbank zurückgegeben:
UserModel.getUsers() .then(docs => { console.log(docs) }) .catch(err => { console.error(err) })
Das Hinzufügen von Instanzmethoden und statischen Methoden ist ein guter Ansatz, um eine Schnittstelle zu Datenbankinteraktionen in Sammlungen und Datensätzen zu implementieren.
Middleware
Middleware sind Funktionen, die in bestimmten Phasen einer Pipeline ausgeführt werden., Mongoose unterstützt Middleware für die folgenden Operationen:
- Aggregat
- Dokument
- Modell
- Abfrage
Zum Beispiel haben Modelle pre
und post
Funktionen, die zwei Parameter annehmen:
- Ereignistyp (‚init‘, ‚validate‘), ’speichern‘, ‚entfernen‘)
- Ein Rückruf, der mit diesem Verweis auf die Modellinstanz ausgeführt wird
Versuchen wir ein Beispiel, indem wir unserem Schema zwei Felder mit dem Namen createdAt
und updatedAt
hinzufügen:
Wenn model.save()
aufgerufen wird, gibt es eine pre(‘save’, …)
und post(‘save’, …)
Ereignis, das ausgelöst wird. Für den zweiten Parameter können Sie eine Funktion übergeben, die beim Auslösen des Ereignisses aufgerufen wird. Diese Funktionen übernehmen einen Parameter für die nächste Funktion in der Middleware-Kette.,
Fügen wir einen Pre-Save-Hook hinzu und setzen Werte für createdAt
und updatedAt
:
Lassen Sie uns unser Modell erstellen und speichern:
Sie sollten Werte für createdAt
und updatedAt
sehen, wenn der erstellte Datensatz gedruckt:
Plugins
Angenommen, wir möchten verfolgen, wann ein Datensatz für jede Sammlung in unserer Datenbank erstellt und zuletzt aktualisiert wurde. Anstatt den obigen Vorgang zu wiederholen, können wir ein Plugin erstellen und auf jedes Schema anwenden.,
Lassen Sie uns eine Datei ./src/model/plugins/timestamp.js
erstellen und die obige Funktionalität als wiederverwendbares Modul replizieren:
Um dieses Plugin zu verwenden, übergeben wir es einfach an die Schemas, denen diese Funktionalität gegeben werden sollte:
Query Building
Mongoose verfügt über eine sehr umfangreiche API, die viele komplexe Operationen verarbeitet, die von MongoDB unterstützt werden. Betrachten Sie eine Abfrage, in der wir schrittweise Abfragekomponenten erstellen können.,
In diesem Beispiel werden wir:
- alle Benutzer Finden
- Überspringen Sie die ersten 100 Datensätze
- die Ergebnisse Begrenzen zu 10 records
- Sortieren Sie die Ergebnisse, indem Sie das Feld Vorname
- Select firstName
- Execute query
Schließen
Wir haben kaum an der Oberfläche gekratzt erkunden einige der Funktionen von Mungo. Es ist eine reichhaltige Bibliothek voller nützlicher und leistungsstarker Funktionen, die es zu einer Freude machen, mit Datenmodellen in der Anwendungsschicht zu arbeiten.,
Während Sie mit Mongo direkt mit Mongo Driver interagieren können, vereinfacht Mongoose diese Interaktion, indem Sie Beziehungen zwischen Daten modellieren und einfach validieren können.
Fun Fact: Mungo wird von Valeri Karpov geschaffen, der ein unglaublich talentierter Ingenieur ist! Er prägte den Begriff Der mittlere Stapel.