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.

Objektzuordnung zwischen Knoten und MongoDB über Mongoose verwaltet

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:

NoSQL Documents vs., Relationale Tabellen in SQL

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):

  1. Laden Sie die entsprechende MongoDB-Version für Ihr Betriebssystem von der MongoDB-Website herunter und folgen Sie deren Installationsanweisungen
  2. Erstellen Sie ein kostenloses Sandbox-Datenbankabonnement auf mLab
  3. 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.

Module import/require work-flow

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):

  1. 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.
  2. Der Wert des Feldes email wird zurückgegeben., Beachten Sie, dass es sich um Kleinbuchstaben handelt, da wir das Attribut lowercase:true im Schema angegeben haben.
  3. __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:

  1. Ereignistyp (‚init‘, ‚validate‘), ’speichern‘, ‚entfernen‘)
  2. Ein Rückruf, der mit diesem Verweis auf die Modellinstanz ausgeführt wird
Beispiel für Middleware (auch bekannt als, pre-und Post-Hooks)

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:

  1. alle Benutzer Finden
  2. Überspringen Sie die ersten 100 Datensätze
  3. die Ergebnisse Begrenzen zu 10 records
  4. Sortieren Sie die Ergebnisse, indem Sie das Feld Vorname
  5. Select firstName
  6. 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.

Wenn dieser Artikel hilfreich war,??? und Folgen Sie mir auf Twitter.

Vielleicht gefällt Ihnen auch mein Workshop auf YouTube: So erstellen Sie eine REST-API mit Node / Express / Mongo