przez Nick Karnik

Mongoose jest biblioteką modelowania danych obiektowych (ODM) dla MongoDB i węzła.js. Zarządza relacjami między danymi, zapewnia walidację schematu i jest używany do tłumaczenia między obiektami w kodzie i reprezentacji tych obiektów w MongoDB.

mapowanie obiektów pomiędzy węzłem a MongoDB zarządzane przez Mongoose

MongoDB jest bezchematyczną bazą danych dokumentów NoSQL., Oznacza to, że możesz przechowywać w nim dokumenty JSON, a struktura tych dokumentów może się różnić, ponieważ nie jest egzekwowana jak bazy danych SQL. Jest to jedna z zalet korzystania z NoSQL, ponieważ przyspiesza tworzenie aplikacji i zmniejsza złożoność wdrożeń.

Poniżej znajduje się przykład przechowywania danych w bazie danych Mongo vs. SQL:

dokumenty NoSQL vs., Tabele relacyjne w SQL

Terminologie

Kolekcje

’Kolekcje' w Mongo są odpowiednikami tabel w relacyjnych bazach danych. Mogą pomieścić wiele dokumentów JSON.

dokumenty

’dokumenty' są odpowiednikami rekordów lub wierszy danych w SQL. Podczas gdy wiersz SQL może odwoływać się do danych w innych tabelach, dokumenty Mongo zwykle łączą to w dokumencie.

pola

’pola' lub atrybuty są podobne do kolumn w tabeli SQL.

schemat

podczas gdy Mongo jest bez schematu, SQL definiuje schemat za pomocą definicji tabeli., Mongoose 'schema' to struktura danych dokumentu (lub kształt dokumentu), która jest wymuszana przez warstwę aplikacji.

Modele

’modele' są konstruktorami wyższego rzędu, które przyjmują schemat i tworzą instancję dokumentu równoważną rekordom w relacyjnej bazie danych.

pierwsze kroki

instalacja Mongo

zanim zaczniemy, skonfigurujmy Mongo., Możesz wybrać jedną z następujących opcji (w tym artykule używamy opcji #1):

  1. Pobierz odpowiednią wersję MongoDB dla Twojego systemu operacyjnego ze strony internetowej MongoDB i postępuj zgodnie z instrukcjami instalacji
  2. Utwórz darmową subskrypcję bazy sandbox w mLab
  3. zainstaluj Mongo używając Dockera jeśli wolisz używać Dockera

przejdźmy przez niektóre podstawy Mongoose, implementując model, który reprezentuje dane dla uproszczonej książki adresowej.

używam Visual Studio Code, Node 8.9 i npm 5.6., Odpal swoje ulubione IDE, Utwórz pusty projekt i zaczynajmy! Będziemy używać ograniczonej składni ES6 w Node, więc nie będziemy konfigurować Babel.

npm Install

przejdźmy do folderu projektu i zainicjalizujmy nasz projekt

npm init -y

zainstalujmy Mongoose i bibliotekę walidacji za pomocą następującego polecenia:

npm install mongoose validator

powyższe polecenie install zainstaluje najnowszą wersję bibliotek. Składnia Mongoose w tym artykule jest specyficzna dla Mongoose v5 i nowszych.,

połączenie z bazą danych

Utwórz plik./src/database.js w katalogu głównym projektu.

następnie dodamy prostą klasę z metodą, która łączy się z bazą danych.

Twój ciąg połączenia będzie się różnić w zależności od instalacji.

powyższe wywołanierequire(‘mongoose’) zwraca obiekt Singleton. Oznacza to, że przy pierwszym wywołaniu require(‘mongoose’) tworzy się instancję klasy Mongoose i zwraca ją., Przy kolejnych wywołaniach zwróci to samo wystąpienie, które zostało utworzone i zwrócone do ciebie po raz pierwszy ze względu na działanie importu/eksportu modułu w ES6.

module import/require work-flow

podobnie, zamieniliśmy naszą klasę bazy danych w singleton zwracając instancję klasy w instrukcjimodule.exports ponieważ potrzebujemy tylko jednego połączenia z bazą danych.,

ES6 bardzo ułatwia nam tworzenie wzorca singleton (pojedynczej instancji) ze względu na sposób działania modułu ładującego poprzez buforowanie odpowiedzi wcześniej zaimportowanego pliku.

schemat mangusty a Model

model mangusty jest opakowaniem na schemacie mangusty. Schemat Mongoose definiuje strukturę dokumentu, wartości domyślne, walidatory itp., natomiast model Mongoose zapewnia interfejs do bazy danych do tworzenia, odpytywania, aktualizacji, usuwania rekordów itp.

Tworzenie modelu Mongoose składa się przede wszystkim z trzech części:

1., Odwołanie do Mongoose

let mongoose = require('mongoose')

to odwołanie będzie takie samo jak to, które zostało zwrócone po podłączeniu do bazy danych, co oznacza, że definicje schematu i modelu nie będą musiały bezpośrednio łączyć się z bazą danych.

2. Definiowanie schematu

schemat definiuje właściwości dokumentu za pomocą obiektu, w którym nazwa klucza odpowiada nazwie Właściwości w kolekcji.,

let emailSchema = new mongoose.Schema({ email: String})

tutaj definiujemy właściwość o nazwie email z ciągiem typu schema, który mapuje do wewnętrznego walidatora, który zostanie uruchomiony po zapisaniu modelu w bazie danych. Nie powiedzie się, jeżeli typ danych wartości nie jest typem string.

dozwolone są następujące typy schematów:

  • tablica
  • Boolean
  • Bufor
  • data
  • Mixed (ogólny / elastyczny typ danych)
  • liczba
  • ObjectId
  • String

Mixed i ObjectId są zdefiniowane w require(‘mongoose’).Schema.Types.

3., Eksportując Model

musimy wywołać konstruktor modelu na instancji Mongoose i przekazać mu nazwę kolekcji oraz odniesienie do definicji schematu.

module.exports = mongoose.model('Email', emailSchema)

połączmy powyższy kod w./src/models/email.js aby zdefiniować zawartość podstawowego modelu poczty e-mail:

definicja schematu powinna być prosta, ale jego złożoność zwykle zależy od wymagań aplikacji. Schematy mogą być ponownie wykorzystane i mogą zawierać kilka schematów potomnych zbyt. W powyższym przykładzie wartość właściwości email jest prostym typem wartości., Jednak może to być również typ obiektu z dodatkowymi właściwościami.

możemy utworzyć instancję modelu zdefiniowanego powyżej i wypełnić go przy użyciu następującej składni:

let EmailModel = require('./email')let msg = new EmailModel({ email: '[email protected]'})

ulepszmy schemat poczty e-mail, aby właściwość email stała się unikalnym, wymaganym polem i przekonwertujmy wartość na małe litery przed jej zapisaniem. Możemy również dodać funkcję walidacji, która zapewni, że wartość jest prawidłowym adresem e-mail. Będziemy odwoływać się i używać biblioteki walidatorów zainstalowanej wcześniej.,

podstawowe operacje

Mongoose posiada elastyczne API i zapewnia wiele sposobów realizacji zadania. Nie skupimy się na wariantach, ponieważ nie jest to możliwe w tym artykule, ale pamiętaj, że większość operacji można wykonać w więcej niż jeden sposób, składniowo lub za pośrednictwem architektury aplikacji.,

Utwórz rekord

Utwórz instancję modelu poczty e-mail i zapisz go w bazie danych:

wynikiem jest dokument, który zostanie zwrócony po pomyślnym zapisaniu:

{ _id: 5a78fe3e2f44ba8f85a2409a, email: '[email protected]', __v: 0 }

zwracane są następujące pola (wewnętrzne pola są poprzedzone podkreśleniem):

  1. _id pole jest automatycznie generowane przez Mongo i jest głównym kluczem kolekcji. Jego wartość jest unikalnym identyfikatorem dokumentu.
  2. zwracana jest wartość polaemail., Zauważ, że jest on mniejszy, ponieważ podaliśmy atrybut lowercase:true w schemacie.
  3. __v jest właściwością versionKey ustawioną na każdym dokumencie po raz pierwszy utworzonym przez Mongoose. Jego wartość zawiera wewnętrzną rewizję dokumentu.

Jeśli spróbujesz powtórzyć powyższą operację zapisu, pojawi się błąd, ponieważ określiliśmy, że pole e-mail powinno być unikalne.

Pobierz rekord

spróbujmy odzyskać rekord zapisany wcześniej w bazie danych., Klasa modelu udostępnia kilka metod statycznych i instancji do wykonywania operacji na bazie danych. Spróbujemy teraz znaleźć rekord, który utworzyliśmy wcześniej za pomocą metody znajdź i przekazać wiadomość e-mail jako wyszukiwany termin.

EmailModel .find({ email: '[email protected]' // search query }) .then(doc => { console.log(doc) }) .catch(err => { console.error(err) })

zwrócony dokument będzie podobny do tego, co było wyświetlane podczas tworzenia rekordu:

{ _id: 5a78fe3e2f44ba8f85a2409a, email: '[email protected]', __v: 0 }

Aktualizuj rekord

zmodyfikujmy powyższy rekord, zmieniając adres e-mail i dodając do niego inne pole, wszystko w ramach jednej operacji., Ze względu na wydajność, Mongoose nie zwróci zaktualizowanego dokumentu, więc musimy przekazać dodatkowy parametr, aby go poprosić:

zwrócony dokument będzie zawierał zaktualizowany adres e-mail:

{ _id: 5a78fe3e2f44ba8f85a2409a, email: '[email protected]', __v: 0 }

Usuń rekord

użyjemy findOneAndRemove aby usunąć rekord., Zwraca oryginalny dokument, który został usunięty:

Helpers

przyjrzeliśmy się niektórym z powyższych podstawowych funkcji znanych jako operacje CRUD( Create, Read, Update, Delete), ale Mongoose zapewnia również możliwość skonfigurowania kilku rodzajów metod i właściwości pomocniczych. Można je wykorzystać do dalszego uproszczenia pracy z danymi.

utwórzmy schemat użytkownika w./src/models/user.js z polamifirstName IlastName:

wirtualna właściwość

wirtualna właściwość nie jest utrzymywana w bazie danych., Możemy dodać go do naszego schematu jako pomocnika, aby uzyskać i ustawić wartości.

utwórzmy wirtualną właściwość o nazwiefullName, która może być używana do ustawiania wartości nafirstName IlastName I pobierzmy je jako wartość kombinowaną podczas odczytu:

wywołania zwrotne dla get I set muszą używać słowa kluczowego function, ponieważ musimy uzyskać dostęp do model poprzez słowo kluczowethis. Używanie funkcji strzałek fat zmieni to, do czego odnosi się this.,

teraz możemy ustawić firstName I lastName przypisując wartość do fullName:

powyższy kod wyda następujące polecenie:

{ _id: 5a7a4248550ebb9fafd898cf, firstName: 'Thomas', lastName: 'Anderson' } Thomas Anderson

metody instancji

możemy tworzyć własne metody pomocnicze na schemacie i uzyskiwać do nich dostęp poprzez instancję modelu. Metody te będą miały dostęp do obiektu modelu i mogą być używane dość kreatywnie. Na przykład, możemy stworzyć metodę, aby znaleźć wszystkie osoby, które mają takie samo imię jak bieżąca instancja.,

w tym przykładzie utwórzmy funkcję zwracającą Inicjały dla bieżącego użytkownika. Dodajmy do schematu własną metodę pomocniczą o nazwie getInitials:

userSchema.methods.getInitials = function() { return this.firstName + this.lastName}

metoda ta będzie dostępna poprzez instancję Modelu:

metody statyczne

podobnie jak metody instancji, możemy tworzyć statyczne metody na schemacie., Stwórzmy metodę pobierania wszystkich użytkowników w bazie danych:

wywołanie getUsers na klasie modelu zwróci wszystkich użytkowników w bazie danych:

UserModel.getUsers() .then(docs => { console.log(docs) }) .catch(err => { console.error(err) })

dodawanie instancji i metod statycznych jest dobrym podejściem do implementacji interfejsu do interakcji z bazą danych na kolekcjach i rekordach.

Middleware

Middleware to funkcje uruchamiane na określonych etapach potoku., Mongoose obsługuje oprogramowanie pośredniczące dla następujących operacji:

  • Agregat
  • dokument
  • Model
  • zapytanie

na przykład modele mają pre I post funkcje, które przyjmują dwa parametry:

  1. typ Z event (’INIT', 'validate', 'save', 'remove')
  2. wywołanie zwrotne, które jest wykonywane z tym odwołaniem do instancji modelu
przykład middleware (alias A.K.A., haki przed i po)

wypróbujmy przykład dodając dwa pola o nazwie createdAt I updatedAt do naszego schematu:

Gdy model.save()pre(‘save’, …)I post(‘save’, …)zdarzenie, które jest wyzwalane. Dla drugiego parametru można przekazać funkcję, która jest wywoływana po wywołaniu zdarzenia. Funkcje te przenoszą parametr do następnej funkcji w łańcuchu middleware.,

dodajmy hook pre-save i ustawmy wartości dla createdAt I updatedAt:

stwórzmy i zapisz nasz model:

powinieneś zobaczyć wartości dla createdAt I updatedAt kiedy tworzony rekord jest drukowany:

wtyczki

Załóżmy, że chcemy śledzić, kiedy rekord został utworzony i ostatnio aktualizowany na każdej kolekcji w naszej bazie danych. Zamiast powtarzać powyższy proces, możemy utworzyć wtyczkę i zastosować ją do każdego schematu.,

stwórzmy plik./src/model/plugins/timestamp.js I powtórzmy powyższą funkcjonalność jako moduł wielokrotnego użytku:

aby użyć tej wtyczki, po prostu przekazujemy ją do schematów, które powinny mieć tę funkcjonalność:

budowanie zapytań

Mongoose ma bardzo bogate API, które obsługuje wiele złożonych operacji obsługiwanych przez MongoDB. Rozważ zapytanie, w którym możemy stopniowo budować komponenty zapytania.,

w tym przykładzie:

  1. Znajdź wszystkich użytkowników
  2. Pomiń pierwsze 100 rekordów
  3. Ogranicz wyniki do 10 rekordów
  4. Sortuj wyniki według pola firstName
  5. Wybierz firstName
  6. wykonaj to zapytanie

zamykanie

ledwo porysowaliśmy powierzchnię, badając niektóre możliwości mangusty. Jest to bogata biblioteka pełna przydatnych i zaawansowanych funkcji, które sprawiają, że praca z modelami danych w warstwie aplikacji jest przyjemnością.,

podczas gdy możesz wchodzić w interakcje z Mongo bezpośrednio za pomocą sterownika Mongo, Mongoose uprości tę interakcję, umożliwiając modelowanie relacji między danymi i łatwe ich walidowanie.

ciekawostka: Mangustę tworzy Valeri Karpov, który jest niezwykle utalentowanym inżynierem! Ukuł termin The MEAN Stack.

Jeśli ten artykuł był pomocny, ??? i śledź mnie na Twitterze.

możesz również polubić mój warsztat na youtube: Jak zbudować REST API z Node / Express / Mongo