Mongoose è un framework JavaScript comunemente utilizzato in un'applicazione Node.js con un database MongoDB. In questo articolo, ho intenzione di presentarvi Mongoose e MongoDB e, soprattutto, dove queste tecnologie si adattano alla vostra applicazione.
Iniziamo con MongoDB. MongoDB è un database che memorizza i tuoi dati come documenti. Più comunemente questi documenti assomigliano a una struttura simile a JSON:
firstName: "Jamie", lastName: "Munro"
Un documento viene quindi inserito in una raccolta. Ad esempio, l'esempio di documento precedente definisce a utente
oggetto. Questo utente
l'oggetto quindi sarebbe in genere parte di una raccolta chiamata utenti
.
Uno dei fattori chiave di MongoDB è la sua flessibilità nella struttura. Anche se nel primo esempio, il utente
oggetto contenuto a nome di battesimo
e cognome
proprietà, queste proprietà non sono richieste in ogni utente
documento che fa parte del utenti
collezione. Questo è ciò che rende MongoDB molto diverso da un database SQL come MySQL o Microsoft SQL Server che richiede uno schema di database fortemente definito di ogni oggetto che memorizza.
La possibilità di creare oggetti dinamici che sono archiviati come documenti nel database è dove entra in gioco la Mongoose.
Mongoose è un Object Document Mapper (ODM). Ciò significa che Mongoose consente di definire oggetti con uno schema fortemente tipizzato mappato su un documento MongoDB.
Mongoose offre un'incredibile quantità di funzionalità attorno alla creazione e all'utilizzo di schemi. Mongoose contiene attualmente otto SchemaTypes che una proprietà viene salvata come quando è persistente in MongoDB. Loro sono:
Ogni tipo di dati consente di specificare:
Oltre a queste opzioni comuni, alcuni tipi di dati consentono di personalizzare ulteriormente il modo in cui i dati vengono archiviati e recuperati dal database. Ad esempio, a Stringa
il tipo di dati consente inoltre di specificare le seguenti opzioni aggiuntive:
Il Numero
e Data
entrambe le proprietà supportano la specifica di un valore minimo e massimo consentito per quel campo.
La maggior parte degli otto tipi di dati consentiti dovrebbe essere abbastanza familiare per te. Tuttavia, ci sono diverse eccezioni che possono saltarti fuori, come ad esempio Buffer
, Misto
, ObjectId
, e schieramento
.
Il Buffer
tipo di dati consente di salvare i dati binari. Un esempio comune di dati binari sarebbe un'immagine o un file codificato, come un documento PDF.
Il Misto
tipo di dati trasforma la proprietà in un campo "qualsiasi cosa va". Questo campo ricorda quanti sviluppatori potrebbero utilizzare MongoDB perché non esiste una struttura definita. Diffidare dell'uso di questo tipo di dati in quanto perde molte delle grandi funzionalità offerte da Mongoose, come la convalida dei dati e il rilevamento delle modifiche delle entità da riconoscere automaticamente per aggiornare la proprietà al momento del salvataggio.
Il ObjectId
tipo di dati indica in genere un collegamento a un altro documento nel database. Ad esempio, se si dispone di una raccolta di libri e autori, il documento del libro potrebbe contenere un ObjectId
proprietà che si riferisce all'autore specifico del documento.
Il schieramento
tipo di dati consente di archiviare array di tipo JavaScript. Con un tipo di dati Array, è possibile eseguire su di essi operazioni comuni su array JavaScript, quali push, pop, shift, slice, ecc.
Prima di passare a generare del codice, volevo solo ricapitolare ciò che abbiamo appena appreso. MongoDB è un database che consente di archiviare i documenti con una struttura dinamica. Questi documenti vengono salvati all'interno di una raccolta.
Mongoose è una libreria JavaScript che consente di definire schemi con dati fortemente tipizzati. Una volta definito uno schema, Mongoose consente di creare un modello in base a uno schema specifico. Un modello Mongoose viene quindi mappato su un documento MongoDB tramite la definizione dello schema del modello.
Dopo aver definito schemi e modelli, Mongoose contiene molte funzioni diverse che consentono di convalidare, salvare, eliminare e interrogare i dati utilizzando le comuni funzioni di MongoDB. Ne parlerò di più con gli esempi di codice concreto da seguire.
Prima di poter iniziare a creare i nostri schemi e modelli Mongoose, MongoDB deve essere installato e configurato. Suggerirei di visitare la pagina di Download di MongoDB. Ci sono diverse opzioni disponibili per l'installazione. Ho collegato al server della comunità. Questo ti permette di installare una versione specifica per il tuo sistema operativo. MongoDB offre anche un server Enterprise e un'installazione di supporto cloud. Dato che potrebbero essere scritti interi libri sull'installazione, l'ottimizzazione e il monitoraggio di MongoDB, ho intenzione di rimanere con il Community Server.
Una volta scaricato e installato MongoDB per il sistema operativo prescelto, sarà necessario avviare il database. Piuttosto che reinventare la ruota, suggerirei di visitare la documentazione di MongoDB su come installare l'edizione della community di MongoDB.
Aspetterò qui mentre configuri MongoDB. Quando sei pronto, possiamo passare alla configurazione di Mongoose per connettersi al tuo database MongoDB appena installato.
Mongoose è un framework JavaScript e lo userò in un'applicazione Node.js. Se hai già installato Node.js, puoi passare al passaggio successivo. Se non hai installato Node.js, ti suggerisco di iniziare visitando la pagina di download di Node.js e selezionando il programma di installazione per il tuo sistema operativo.
Con Node.js installato e pronto per andare, creerò una nuova applicazione e installerò il pacchetto Mongoose NPM.
Con un prompt dei comandi impostato su dove si desidera installare l'applicazione, è possibile eseguire i seguenti comandi:
mkdir mongoose_basics cd mongoose_basics npm init
Per l'inizializzazione della mia applicazione, ho lasciato tutto come valori predefiniti. Ora installerò il pacchetto mongoose come segue:
npm install mongoose --save
Con tutti i prerequisiti configurati, connettiamoci a un database MongoDB. Ho inserito il seguente codice all'interno di un file index.js perché l'ho scelto come punto di partenza per la mia applicazione:
var mongoose = require ('mangusta'); mongoose.connect ( 'mongodb: // localhost / mongoose_basics');
La prima riga di codice include il mangusta
biblioteca. Successivamente, apro una connessione a un database che ho chiamato mongoose_basics
usando il Collegare
funzione.
Il Collegare
la funzione accetta altri due parametri opzionali. Il secondo parametro è un oggetto di opzioni in cui è possibile definire cose come nome utente e password, se necessario. Il terzo parametro, che può anche essere il secondo parametro se non si dispone di opzioni, è la funzione di callback dopo il tentativo di connessione. La funzione di callback può essere utilizzata in due modi:
mongoose.connect (uri, options, function (error) // Controlla l'errore nella connessione iniziale Non c'è il secondo parametro per il callback.); // Oppure usa promises mongoose.connect (uri, options) .then (() => / ** pronto per l'uso. La promessa 'mongoose.connect ()' si risolve in undefined. * /, Err => / ** gestisce l'errore di connessione iniziale * /);
Per evitare una potenziale introduzione alle Promesse di JavaScript, userò la prima. Di seguito è riportato un file index.js aggiornato:
var mongoose = require ('mangusta'); mongoose.connect ('mongodb: // localhost / mongoose_basics', function (err) if (err) genera err; console.log ('Successfully connected'););
Se si verifica un errore durante la connessione al database, viene generata l'eccezione e tutte le ulteriori elaborazioni vengono interrotte. Quando non si verifica alcun errore, ho registrato un messaggio di successo sulla console.
Mongoose è ora configurato e connesso a un database chiamato mongoose_basics
. La mia connessione MongoDB non utilizza nome utente, password o porta personalizzata. Se è necessario impostare queste opzioni o qualsiasi altra opzione durante la connessione, suggerisco di rivedere la documentazione di Mongoose al momento della connessione. La documentazione fornisce spiegazioni dettagliate sulle numerose opzioni disponibili e su come creare più connessioni, pool di connessioni, repliche, ecc.
Con una connessione riuscita, passiamo alla definizione di uno schema Mongoose.
Durante l'introduzione, ho mostrato a utente
oggetto che conteneva due proprietà: nome di battesimo
e cognome
. Nell'esempio seguente, ho tradotto quel documento in uno schema di Mongoose:
var userSchema = mongoose.Schema (firstName: String, lastName: String);
Questo è uno schema molto semplice che contiene solo due proprietà senza attributi associati ad esso. Espandiamo questo esempio convertendo le proprietà del nome e del cognome in oggetti figlio di a nome
proprietà. Il nome
la proprietà comprenderà sia il nome che il cognome. Aggiungerò anche un creato
proprietà che è di tipo Data
.
var userSchema = mongoose.Schema (name: firstName: String, lastName: String, creato: Date);
Come puoi vedere, Mongoose mi consente di creare schemi molto flessibili con molte diverse combinazioni possibili di come sono in grado di organizzare i miei dati.
Nel prossimo esempio, creerò due nuovi schemi che illustreranno come creare una relazione con un altro schema: autore
e libro
. Il libro
lo schema conterrà un riferimento al autore
schema.
var authorSchema = mongoose.Schema (_id: mongoose.Schema.Types.ObjectId, nome: firstName: String, lastName: String, biografia: String, twitter: String, facebook: String, linkedin: String, profilePicture: Buffer, creato: tipo: Data, default: Date.now);
Sopra è il autore
schema che espande i concetti del utente
schema che ho creato nell'esempio precedente. Per collegare l'Autore e il Libro insieme, la prima proprietà del autore
lo schema è un _ID
proprietà che è un ObjectId
tipo di schema. _ID
è la sintassi comune per la creazione di una chiave primaria in Mongoose e MongoDB. Quindi, come il utente
schema, ho definito a nome
proprietà contenente il nome e il cognome dell'autore.
Espansione sul utente
schema, il autore
contiene molti altri Stringa
tipi di schema. Ho anche aggiunto un Buffer
tipo di schema che potrebbe contenere l'immagine del profilo dell'autore. La proprietà finale contiene la data di creazione dell'autore; tuttavia, potresti notare che è stato creato in modo leggermente diverso perché ha definito un valore predefinito di "now". Quando un autore è persistente nel database, questa proprietà verrà impostata sulla data / ora corrente.
Per completare gli esempi di schema, creiamo a libro
schema che contiene un riferimento all'autore usando il ObjectId
tipo di schema:
var bookSchema = mongoose.Schema (_id: mongoose.Schema.Types.ObjectId, titolo: String, riepilogo: String, isbn: String, miniatura: Buffer, autore: tipo: mongoose.Schema.Types.ObjectId, ref: ' Autore ', classificazioni: [riepilogo: Stringa, dettaglio: Stringa, numeroDiFosse: Numero, creato: tipo: Data, default: Date.now], creato: tipo: Data, default: Date.now );
Il libro
schema contiene diverse proprietà di tipo Stringa
. Come accennato in precedenza, contiene un riferimento al autore
schema. Per dimostrare ulteriormente le potenti definizioni dello schema, il libro
lo schema contiene anche un schieramento
di giudizi
. Ogni valutazione consiste di a sommario
, dettaglio
, numberOfStars
, e creato
data proprietà.
Mongoose ti offre la flessibilità di creare schemi con riferimenti ad altri schemi o, come nell'esempio precedente con il giudizi
proprietà, ti permette di creare un schieramento
di proprietà figlio che potrebbero essere contenute in uno schema correlato (come libro per autore) o in linea come nell'esempio precedente (con il libro in base a valutazioni schieramento
).
Dal momento che il autore
e libro
gli schemi dimostrano la flessibilità dello schema di Mongoose, ho intenzione di continuare a usare quegli schemi e derivarne uno Autore
e Libro
modello da loro.
var Autore = mongoose.model ('Autore', authorSchema); var Book = mongoose.model ('Book', bookSchema);
Un modello Mongoose, una volta salvato, crea un documento in MongoDB con le proprietà definite dallo schema da cui deriva.
Per dimostrare la creazione e il salvataggio di un oggetto, nel prossimo esempio, creerò diversi oggetti: a Autore
Modello e diversi Libro
Modelli. Una volta creati, questi oggetti saranno mantenuti su MongoDB usando il salvare
metodo del modello.
var jamieAuthor = new Autore _id: new mongoose.Types.ObjectId (), nome: firstName: 'Jamie', lastName: 'Munro', biografia: 'Jamie è l'autore di ASP.NET MVC 5 con Bootstrap e Knockout .js. ', twitter:' https://twitter.com/endyourif ', facebook:' https://www.facebook.com/End-Your-If-194251957252562/ '; jamieAuthor.save (function (err) if (err) throw err; console.log ('Autore salvato con successo.'); var mvcBook = new Book _id: new mongoose.Types.ObjectId (), titolo: 'ASP. NET MVC 5 con Bootstrap e Knockout.js ', autore: jamieAuthor._id, classificazioni: [summary:' Great read ']; mvcBook.save (function (err) if (err) throw err; console.log ('Libro salvato correttamente.');); Var knockoutBook = nuovo Libro _id: new mongoose.Types.ObjectId (), titolo: 'Knockout.js: Creazione di applicazioni Web dinamiche lato client', autore: jamieAuthor._id ; knockoutBook.save (function (err) if (err) throw err; console.log ('Book successfully saved.');););
Nell'esempio sopra, ho inserito senza vergogna un riferimento ai miei due libri più recenti. L'esempio inizia creando e salvando a jamieObject
che è stato creato da unAutore
Modello. Dentro il salvare
funzione del jamieObject
, se si verifica un errore, l'applicazione emetterà un'eccezione. Quando il salvataggio ha successo, all'interno di salvare
funzione, i due oggetti del libro vengono creati e salvati. Simile al jamieObject
, se si verifica un errore durante il salvataggio, viene emesso un errore; in caso contrario, viene emesso un messaggio di successo nella console.
Per creare il riferimento all'autore, gli oggetti del libro fanno riferimento entrambi autore
lo schema di _ID
chiave primaria nel autore
proprietà del libro
schema.
È abbastanza comune per i dati che finiranno per creare un modello da compilare da un modulo su una pagina web. Per questo motivo, è una buona idea convalidare questi dati prima di salvare il Modello in MongoDB.
Nel prossimo esempio, ho aggiornato lo schema dell'autore precedente per aggiungere la convalida sulle seguenti proprietà: nome di battesimo
, cinguettio
, Facebook
, e linkedin
.
var authorSchema = mongoose.Schema (_id: mongoose.Schema.Types.ObjectId, nome: firstName: tipo: String, obbligatorio: true, lastName: String, biografia: String, twitter: tipo: String, convalida : validator: function (text) return text.indexOf ('https://twitter.com/') === 0;, messaggio: 'L'handle di Twitter deve iniziare con https://twitter.com/' , facebook: type: String, validate: validator: function (text) return text.indexOf ('https://www.facebook.com/') === 0;, messaggio: 'Facebook deve iniziare con https://www.facebook.com/ ', linkedin: type: String, validate: validator: function (text) return text.indexOf (' https://www.linkedin.com/ ') === 0;, messaggio: 'LinkedIn deve iniziare con https://www.linkedin.com/', profilePicture: Buffer, creato: tipo: Data, default: Date.now);
Il nome di battesimo
proprietà è stata attribuita con il necessario
proprietà. Ora quando chiamo il salvare
funzione, Mongoose restituirà un errore con un messaggio che indica il nome di battesimo
la proprietà è richiesta Ho scelto di non fare il cognome
proprietà richieste nel caso in cui Cher o Madonna dovessero essere autori nel mio database.
Il cinguettio
, Facebook
, e linkedin
tutte le proprietà hanno validatori personalizzati molto simili a loro applicati. Ciascuno assicura che i valori inizino con il rispettivo nome di dominio dei social network. Questi campi non sono richiesti, quindi il validatore verrà applicato solo quando i dati vengono forniti per quella proprietà.
Un'introduzione a Mongoose non sarebbe completa senza un esempio di ricerca di un record e l'aggiornamento di una o più proprietà su quell'oggetto.
Mongoose offre diverse funzioni per trovare i dati per un modello specifico. Le funzioni sono trova
, trova uno
, e findById
.
Il trova
e trova uno
entrambe le funzioni accettano un oggetto come input che consente ricerche complesse, mentre findById
accetta solo un singolo valore con una funzione di callback (ne seguirà a breve un esempio). In questo prossimo esempio, ho intenzione di dimostrare come trovare tutti i libri che contengono la stringa "mvc" nel loro titolo.
Book.find (title: / mvc / i). Exec (function (err, books) if (err) throw err; console.log (libri););
Dentro il trova
funzione, sto cercando la stringa "mvc" senza distinzione tra maiuscole e minuscole titolo
proprietà. Questo si ottiene usando la stessa sintassi per cercare una stringa con JavaScript.
La chiamata della funzione di ricerca può anche essere concatenata ad altri metodi di query, come dove
, e
, o
, limite
, ordinare
, qualunque
, eccetera.
Espandiamo l'esempio precedente per limitare i risultati ai primi cinque libri e ordinare la data di creazione decrescente. Ciò restituirà i cinque libri più recenti contenenti "mvc" nel titolo.
Book.find (title: / mvc / i). Sort ('- created') .limit (5) .exec (function (err, books) if (err) throw err; console.log (libri); );
Dopo aver applicato il trova
funzione, l'ordine delle altre funzioni non è importante perché tutte le funzioni concatenate vengono compilate insieme in una singola query e non eseguito fino al exec
la funzione è chiamata.
Come ho detto prima, il findById
viene eseguito un po 'diversamente. Esegue immediatamente e accetta una funzione di callback, invece di consentire una catena di funzioni. Nel prossimo esempio, sto interrogando un autore specifico con il loro _ID
.
Author.findById ('59b31406beefa1082819e72f', function (err, author) if (err) genera err; console.log (autore););
Il _ID
nel tuo caso potrebbe essere leggermente diverso. Ho copiato questo _ID
da un precedente console.log
quando trovi un elenco di libri con "mvc" nel titolo.
Una volta che un oggetto è stato restituito, è possibile modificare qualsiasi proprietà per aggiornarlo. Una volta apportate le modifiche necessarie, si chiama il salvare
metodo, proprio come quando stavi creando l'oggetto. Nel prossimo esempio, estenderò il findbyId
esempio e aggiornare il linkedin
proprietà sull'autore.
Author.findById ('59b31406beefa1082819e72f', funzione (err, autore) if (err) gettare err; author.linkedin = 'https://www.linkedin.com/in/jamie-munro-8064ba1a/'; author.save (function (err) if (err) throw err; console.log ('Autore aggiornato correttamente');););
Dopo che l'autore è stato recuperato con successo, il linkedin
la proprietà è impostata e il salvare
la funzione è chiamata. Mongoose è in grado di rilevare che il linkedin
la proprietà è stata modificata e invierà una dichiarazione di aggiornamento a MongoDB solo sulle proprietà che sono state modificate. Se si verifica un errore durante il salvataggio, verrà generata un'eccezione e l'applicazione verrà arrestata. In caso di successo, viene registrato un messaggio di successo sulla console.
Mongoose offre anche due funzioni aggiuntive che consentono di trovare un oggetto e di salvarlo in un unico passaggio con le funzioni appropriatamente denominate: findByIdAndUpdate
e findOneAndUpdate
. Aggiorniamo l'esempio precedente per utilizzare il findByIdAndUpdate
.
Author.findByIdAndUpdate ('59b31406beefa1082819e72f', linkedin: 'https://www.linkedin.com/in/jamie-munro-8064ba1a/', funzione (err, autore) if (err) genera err; console.log (autore););
Nell'esempio precedente, le proprietà da aggiornare vengono fornite come oggetto al secondo parametro di findByIdAndUpdate
funzione. La funzione di callback è ora il terzo parametro. Quando l'aggiornamento ha esito positivo, il autore
oggetto restituito contiene le informazioni aggiornate. Questo viene registrato nella console per vedere le proprietà dell'autore aggiornato.
In questo articolo, ho fornito piccoli snippet di codice che identificano un'azione molto specifica, come la creazione di uno schema, la creazione di un modello, ecc. Mettiamo tutto insieme in un esempio completo.
In primo luogo, ho creato due file aggiuntivi: author.js
e book.js
. Questi file contengono le rispettive definizioni dello schema e la creazione del modello. La riga finale del codice rende il modello disponibile per l'uso in index.js
file.
Iniziamo con il file author.js:
var mongoose = require ('mangusta'); var authorSchema = mongoose.Schema (_id: mongoose.Schema.Types.ObjectId, nome: firstName: tipo: String, obbligatorio: true, lastName: String, biografia: String, twitter: tipo: String, convalida : validator: function (text) return text.indexOf ('https://twitter.com/') === 0;, messaggio: 'L'handle di Twitter deve iniziare con https://twitter.com/' , facebook: type: String, validate: validator: function (text) return text.indexOf ('https://www.facebook.com/') === 0;, messaggio: 'Facebook deve iniziare con https://www.facebook.com/ ', linkedin: type: String, validate: validator: function (text) return text.indexOf (' https://www.linkedin.com/ ') === 0;, messaggio: 'LinkedIn deve iniziare con https://www.linkedin.com/', profilePicture: Buffer, creato: tipo: Data, default: Date.now); var Autore = mongoose.model ('Autore', authorSchema); module.exports = Autore;
Poi arriva il book.js
file:
var mongoose = require ('mangusta'); var bookSchema = mongoose.Schema (_id: mongoose.Schema.Types.ObjectId, titolo: String, riepilogo: String, isbn: String, miniatura: Buffer, autore: tipo: mongoose.Schema.Types.ObjectId, ref: ' Autore ', classificazioni: [riepilogo: Stringa, dettaglio: Stringa, numeroDiFosse: Numero, creato: tipo: Data, default: Date.now], creato: tipo: Data, default: Date.now ); var Book = mongoose.model ('Book', bookSchema); module.exports = Book;
E infine, l'aggiornato index.js
file:
var mongoose = require ('mangusta'); var Author = require ('./ author'); var Book = require ('./ book'); mongoose.connect ('mongodb: // localhost / mongoose_basics', function (err) if (err) genera err; console.log ('Successfully connected'); var jamieAuthor = new Autore (_id: new mangusta.Types. ObjectId (), nome: firstName: 'Jamie', lastName: 'Munro', biografia: 'Jamie è l'autore di ASP.NET MVC 5 con Bootstrap e Knockout.js.', Twitter: 'https: // twitter .com / endyourif ', facebook:' https://www.facebook.com/End-Your-If-194251957252562/ '); jamieAuthor.save (function (err) if (err) throw err, console.log ('Autore salvato con successo.'); Var mvcBook = new Book (_id: new mongoose.Types.ObjectId (), titolo: 'ASP.NET MVC 5 con Bootstrap e Knockout.js', autore: jamieAuthor._id, classificazioni : [summary: 'Great read']); mvcBook.save (function (err) if (err) throw err; console.log ('Book salvato con successo.');); var knockoutBook = new Book (_id: new mongoose.Types.ObjectId (), titolo: "Knockout.js: creazione di applicazioni Web dinamiche lato client", autore: jamieAuthor._id); knockoutBook.save (funct ion (err) if (err) gettare err; console.log ('Libro salvato correttamente.'); ); ); );
Nell'esempio sopra, tutte le azioni di Mongoose sono contenute all'interno di Collegare
funzione. Il autore
e libro
i file sono inclusi con richiedere
funzione dopo aver incluso il mangusta
biblioteca.
Con MongoDB in esecuzione, ora puoi eseguire l'applicazione Node.js completa con il seguente comando:
nodo index.js
Dopo aver salvato alcuni dati nel mio database, ho aggiornato il file index.js
file con le funzioni di ricerca come segue:
var mongoose = require ('mangusta'); var Author = require ('./ author'); var Book = require ('./ book'); mongoose.connect ('mongodb: // localhost / mongoose_basics', function (err) if (err) genera err; console.log ('Successfully connected'); Book.find (title: / mvc / i). sort ('- created') .limit (5) .exec (funzione (err, books) if (err) throw err; console.log (libri);); Author.findById ('59b31406beefa1082819e72f', funzione (err , autore) if (err) throw err; author.linkedin = 'https://www.linkedin.com/in/jamie-munro-8064ba1a/'; author.save (function (err) if (err) throw err, console.log ('Autore aggiornato correttamente'););); Autore.findByIdAndUpdate ('59b31406beefa1082819e72f', linkedin: 'https://www.linkedin.com/in/jamie-munro-8064ba1a/' , function (err, author) if (err) throw err; console.log (author);););
Ancora una volta, puoi eseguire l'applicazione con il comando: nodo index.js
.
Dopo aver letto questo articolo, dovresti essere in grado di creare schemi e modelli Mongoose estremamente flessibili, applicare convalide semplici o complesse, creare e aggiornare documenti e infine cercare i documenti che sono stati creati.
Speriamo che ora ti senta a tuo agio con l'uso di Mongoose. Se stai cercando di saperne di più, ti suggerisco di rivedere le Guide Mongoose che approfondiscono argomenti più avanzati come popolazione, middleware, promesse, ecc..
Buona caccia (scarsa referenza animale Mongoose)!