{"id":28797776,"url":"https://github.com/john-azzaro/study-mongoose-configuration-and-data-modeling","last_synced_at":"2026-05-15T21:04:09.029Z","repository":{"id":299209289,"uuid":"211001880","full_name":"john-azzaro/Study-Mongoose-Configuration-and-Data-Modeling","owner":"john-azzaro","description":"A handy study in the implementation of Mongoose, including Mongoose fundamentals, server configuration, Mongoose Schema, Models, virtual properties, and instance methods.","archived":false,"fork":false,"pushed_at":"2023-03-03T07:46:58.000Z","size":123,"stargazers_count":0,"open_issues_count":5,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-15T10:57:08.036Z","etag":null,"topics":["instance-methods","mongoose","mongoose-fundamentals","mongoose-model","mongoose-schema","mongoose-server","virtual-properties"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/john-azzaro.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-09-26T04:47:40.000Z","updated_at":"2019-11-06T05:33:20.000Z","dependencies_parsed_at":"2025-06-15T10:57:19.535Z","dependency_job_id":"215eb05f-1773-4dab-b424-14f31f0a198b","html_url":"https://github.com/john-azzaro/Study-Mongoose-Configuration-and-Data-Modeling","commit_stats":null,"previous_names":["john-azzaro/study-mongoose-configuration-and-data-modeling"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/john-azzaro/Study-Mongoose-Configuration-and-Data-Modeling","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/john-azzaro%2FStudy-Mongoose-Configuration-and-Data-Modeling","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/john-azzaro%2FStudy-Mongoose-Configuration-and-Data-Modeling/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/john-azzaro%2FStudy-Mongoose-Configuration-and-Data-Modeling/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/john-azzaro%2FStudy-Mongoose-Configuration-and-Data-Modeling/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/john-azzaro","download_url":"https://codeload.github.com/john-azzaro/Study-Mongoose-Configuration-and-Data-Modeling/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/john-azzaro%2FStudy-Mongoose-Configuration-and-Data-Modeling/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262536737,"owners_count":23325800,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["instance-methods","mongoose","mongoose-fundamentals","mongoose-model","mongoose-schema","mongoose-server","virtual-properties"],"created_at":"2025-06-18T05:01:05.946Z","updated_at":"2026-05-15T21:04:03.997Z","avatar_url":"https://github.com/john-azzaro.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Mongoose Configuration and Data Modeling Study\n\n## What is the Mongoose Configuration and Data Modeling Study?\nMongoose allows your Node.js app to talk to the MongoDB database. **Mongoose Configuration and Data Modeling Study** is an examination of Mongoose basics, the configuration of Mongoose server, and data modeling using schemas, models, virtuals, and instance methods. Please note that due to the amount of information in this study, I've split Mongoose study into two parts, \"Mongoose Study\" and \"Mongoose CRUD Operations\". Additionally, I've created speerate studies that address topics such as [**schemas**](https://github.com/john-azzaro/Study-Mongoose-Schemas \"schemas\") seperately for more in-depth examination.\n\n\u003cbr\u003e\n\nHere's some questions covered in the study:\n\n* [What is Mongoose?](#What-is-Mongoose)\n* [How do you setup and configure a Mongoose server?](#How-do-you-setup-and-configure-a-Mongoose-server)\n* [What is a Mongoose Schema and why do you need it?](#What-is-a-Mongoose-Schema-and-why-do-you-need-it)\n* [How do you create a Mongoose Schema?](#How-do-you-create-a-Mongoose-Schema)\n* [What is a Mongoose Model?](#What-is-a-Mongoose-Model)\n* [How do you create a Mongoose Model?](#How-do-you-create-a-Mongoose-Model)\n* [What are Virtuals?](#What-are-Virtuals)\n* [How do you define a virtual property?](#How-do-you-define-a-virtual-property)\n* [What is an instance method and how do you implement it?](#What-is-an-instance-method-and-how-do-you-implement-it)\n* [How do Schemas and Models work with CRUD operations?](#How-do-Schemas-and-Models-work-with-CRUD-operations)\n\n\n\u003cbr\u003e\n\n## What is Mongoose?\nMongoose is a Object Data Mapper (ODM) library (or Object Modeling Modeler) for MongoDB and Node.js.\n\nThe primary objective of the Mongoose framework is to simplify the writing of validation code, business logic boiler plate, and make the code shorter and easier to work with. In more technical terms, Mongoose provides a modeling enviroment for your data, enforcing structure while maintaing flexibility. Mongoose manages realtionships between data, providing schema validation, and is used between objects in code and the representation of those object in MongoDB.\n\n\n\u003cbr\u003e\n\n## How do you setup and configure a Mongoose server?\nTo setup Mongoose, you need to install the Mongoose depency, configure Mongoose to use ES6 promises (for pre-version 5 Mongoose). Then, you can add your database url's and environment variables either in the server.js file or (as in this study), in a seperate config.js file.  Lastly, add a runServer and a closeServer function to connect with MongoDB and listen for connections and close the server when disconnected.\n\n\u003cdl\u003e\n\n### STEP 1: Install the Node package \"mongoose\":\n-----\n\u003cdd\u003e\n\nInstall mongoose from node package manager.\n```\n    npm install mongoose\n```\n\u003c/dd\u003e\n\n### STEP 2: Import mongoose into your server.js file:\n------\n\u003cdd\u003e\n\nThis is pretty much a standard importation of the mongoose package you previously installed to your dependencies.\n```JavaScript\n    const express = require('express')                                               // import express.\n    const mongoose = require('mongoose');                                            // import mongoose.\n```\n\u003c/dd\u003e\n\n### STEP 3: Configure Mongoose to use ES6 Promises:\n------\n\u003cdd\u003e\n\nAlthough this is legacy code and isnt needed with Mongoose 5+, you should insert this statement to make Mongoose use built-in ES6 promises.\n```JavaScript\n    const express = require('express');\n    const mongoose = require('mongoose');\n\n    mongoose.Promise = global.Promise;                                         // Add ES6 Promise support.\n```\n\u003c/dd\u003e\n\n### STEP 4: Import values from config.js file:\n------\n\u003cdd\u003e\n\n1. Because the config.js file is where you can control the constants for the entire app. In this way, you can also create development environment variables if\nneeded. So first, create a config.js file. \n```\n    config.js\n```\n\n\u003cbr\u003e\n\n2. Then inside the config.js file, we have 3 constants: the database url, the test database url, and the port number we want the app to listen for (i.e. 8080). This helps us easily find the variables when needed.\n\n\u003e NOTE: If you want to set an environment variable, you can do so in TWO ways: Temporarily before you run the program OR set for the complete session. In the case of setting your environment variable temporarily: ```PORT=3000 node server.js```. In the case an environment variable for the complete session: ```export PORT=3000 node server.js```.\n```JavaScript\n    exports.DATABASE_URL = process.env.DATABASE_URL || \"mongodb://localhost/books\";\n    exports.TEST_DATABASE_URL = process.env.TEST_DATABASE_URL || \"mongodb://localhost/test-books\";\n    exports.PORT = process.env.PORT || 8080;\n```\n\n\u003cbr\u003e\n\n3. Finally, we import the values from the config.js file to the server.js file.  We simply import from the config file and pull the variables we want (i.e. PORT and DATABASE_URL).\n```Javascript\n    const express = require('express');\n    const mongoose = require('mongoose');\n\n    mongoose.Promise = global.Promise;\n\n    const { PORT, DATABASE_URL } = require(\"./config\");       // import PORT and DATABASE_URL from config.js.\n```\n\n\u003c/dd\u003e\n\n### STEP 5: Create a \"runServer\" function to connect to database and run HTTP server!\n------\n\u003c/dd\u003e\n\nSo essentially the runServer function will connect to the MongoDB database and run the HTTP server in unison.  It does this in a specific order:\n1. Mongoose connects to our database using the URL's we provided in the config.js file.\n2. Listen for connections on the ports we specified (i.e. 8080 OR other specified env variable port).\n3. If successful, call a callback function if that connection worked. If unsuccessful, return error.\n\n```JavaScript\n    let server;                                                    // server declared OUTSIDE Run and Close.\n \n    function runServer(databaseUrl, port=PORT) {                   // To Run server: \n        return new Promise((resolve, reject) =\u003e {                  // return Promise in which...\n            mongoose.connect(databaseUrl, err =\u003e {                 // Mongoose connects to database:\n                if (err) {                                         // If there is an error... \n                    return reject(err);                            // ... return reject.\n                }       \n\n                server = app.listen(port, () =\u003e {                  // Listen for connection to configured port.  \n                    console.log(`Listening on port ${port}`);      // ... and log connection in terminal.\n                    resolve();                                     // and then the promise is resolved!\n                })\n                .on('error', err =\u003e {                              // But if there is an error...\n                    mongoose.disconnect();                         // ... disconnect from mongoose...\n                    reject(err);                                   // and reject (passing in an error object).\n                });\n            });\n        });\n    }\n```\n\n\u003c/dd\u003e\n\n### STEP 6: Create a \"closeServer\" to disconnect from database and close app:\n------\n\u003c/dd\u003e\n\nThis closes the app as well as disconnects from the database. This also returns a promise, which is doen for testing, and accesses the server object which was created in runServer.\n\n```JavaScript\n    function closeServer() {                                     // To close server:\n        return mongoose.disconnect().then(() =\u003e {                // disconnect and then...\n            return new Promise((resolve, reject) =\u003e {            // return a promise which...\n                console.log(\"Closing server\");                   // ... will log \"closing server\"...\n                server.close(err =\u003e {                            // and close the server...\n            if (err) {                                           // and if there is an error, reject...\n               return reject(err);                                  \n            }\n            resolve();                                           // else resolve.\n        });\n        });\n    });\n    }\n```\n\u003c/dd\u003e\n\n### STEP 7: Create direct server.js call block:\n-------\n\u003cdd\u003e\n\nIn the event that the application is called using ```node server.js``` or something to that effect, this block will run as a contingency. \n```JavaScript\n    if (require.main === module) {                                                             \n        runServer(DATABASE_URL).catch(err =\u003e console.error(err));\n    }\n\n```\n\n\n\n\u003c/dd\u003e\n\n\u003c/dl\u003e\n\n\u003cbr\u003e\n\n## What is a Mongoose Schema and why do you need it?\n\u003cdl\u003e\n\u003cdd\u003e\n\nA **schema** is used to define the shape (i.e. layers of properties) of documents within a collection in MongoDB. \n\nWhy do you need a schema? A schema is a template that you can plug data into and save in a collection inside your database. For instance, in MongoDB Compass \nfor each database you will see \"collections\". A \"document\" in a MongoDB \"collection\" is an individual instance of each \nschema with unique values in the standard properties.\n\n\n\u003c/dd\u003e\n\u003c/dl\u003e\n\n\u003cbr\u003e\n\n\n## How do you create a Mongoose Schema?\n\u003cdl\u003e\n\u003cdd\u003e\n\nTo create a schema, you first need to create a \"blueprint\" of your document. This define the shape of the document you wish to create.  \n\n\u003e In the following example, we'll create schema for a book with associated properties (i.e. name, author, etc.).\n\n\u003c/dd\u003e\n\u003c/dl\u003e\n\n### First, we set the \"bookSchema\" to a new schema class:\n\n\u003cdl\u003e\n\u003cdd\u003e\n\nThis basically creates a new schema when the \"bookSchema\" is called. And because this creates a new instance of the class, you pass an object with the key/value pairs\nin the books documents. So again, this book \"schema\" will define the shape (i.e. layout) of the book documents (i.e. individual instances) in the Mongo Database.\n```JavaScript\n    const bookSchema = new mongoose.Schema({\n        // properties of book go here.\n    })\n```\n\n\u003c/dd\u003e\n\u003c/dl\u003e\n\n### Second, specify the properties your document has:\n\n\u003cdl\u003e\n\u003cdd\u003e\n\nWhen you create your schema, you are going to need to have specific attributes that document has.  Thus, for each an every book schema that is created you need to have properties such as a name, author, isPublished, etc. \n\nNow take for example the \"author\" property. This property has a schema type of \"String\" which maps to an internal validator that will be triggered when the model is saved to MongoDB. If the data type is anything other than a String, it will fail because it is not a string type. \n\n ```JavaScript\n    const bookSchema = new mongoose.Schema({             // Schema that will represent a book:\n        name: {                                          // object with type property and required value.\n            type: String, \n            required: true\n        },            \n        authors: String,                                 // string.\n        tags: [ String ],                                // array of string values.                 \n        isPublished: Boolean                             // boolean\n        date: { type: Date, default: Date.now },         // date (set to the date created).\n        reviews: [{                                      // array of objects\n            reviewer: String,\n            publication: String,\n            grade: Number,\n            date: Date\n        }]\n    })\n```\n\nAlso note that when creating schemas, you can use only the following data types: \n\n| **Data Type:**                            | **Example:**                             |\n| ---------------------------------------- | ----------------------------------------------|\n|    *String*                                      |          Joe Smith                                     |\n|     *Number*                                     |           12345                                    |\n|    *Date*                                      |         2019-06-29T22:34:02.188Z                                      |\n|    *Boolean*                                      |       true                                        |\n|    *Array*                                       |         [red, yellow, green]                                      |\n|    *Object*                                       |         {name: String, age: Number}                                      |\n\n\n\u003c/dd\u003e\n\u003c/dl\u003e\n\n\n\n\u003cbr\u003e\n\n## What is a Mongoose Model?\n\n\u003cdl\u003e\n\u003cdd\u003e\n\nA **Mongoose model** is a wrapper on the Mongoose schema.\n\nWhile the *schema* defines the structure of the document, like the default values, validators, etc., the Mongoose *model* provides the interface to the database for creating, querying, updating, deleting, etc.\n\n\u003c/dd\u003e\n\u003c/dl\u003e\n\n\u003cbr\u003e\n\n## How do you create a Mongoose Model?\nTo create a model, we need to follow a three step process: \n1. Reference Mongoose\n2. Define the Schema\n3. Export the model\n\n### STEP 0: Create a models file.\n\u003cdl\u003e\n\u003cdd\u003e\n\n```\n    models.js\n```\n\n\u003c/dd\u003e\n\u003c/dl\u003e\n\n### STEP 1: Reference Mongoose.\n\u003cdl\u003e\n\u003cdd\u003e\n\n```JavaScript\n    const mongoose = require('mongoose');              //load mongoose\n```\n\n\u003c/dd\u003e\n\u003c/dl\u003e\n\n### STEP 2: Define the Schema.\n\u003cdl\u003e\n\u003cdd\u003e\n\nAs we covered in the previous \"What is a Mongoose Schema\" section, you are simply creating a template for any instance of books you will create. \n```JavaScript\n    const mongoose = require(\"mongoose\");\n\n    const bookSchema = new mongoose.Schema({          // schema of book\n            title: {                      \n                titleName: String,\n                type: String, \n                required: true\n            },            \n            authorName: {\n                firstName: String,\n                lastName: String,\n            }        \n            tags: [ String ],                   \n            isPublished: Boolean,      \n            date: { type: Date, default: Date.now },  \n            reviews: [{               \n                reviewer: String,\n                publication: String,\n                grade: Number,\n                date: Date\n            }]\n    })\n```\n\n\u003c/dd\u003e\n\u003c/dl\u003e\n\n### STEP 3: Export the model.\n\u003cdl\u003e\n\u003cdd\u003e\n\nNow that you have your schema, you need to package it a model to be exported elsewhere in your code. To do this, you need to do the following:\n\n1. Tell mongoose top create a new model:\n    ```JavaScript\n        mongoose.model();\n    ```\n2. Pass in TWO arguments: The corresponding collection in your database and the schema:\nWhen you tell mongoose to create a model, the first argument you pass in will be the collection in the database that corresponds to this model. The second argument will be the schema we just defined. Also note that by default, Mongo will convert convert the name of the first argument (i.e. Book =\u003e books), where it will be working with ``` db.books```.\n\n    ```JavaScript\n        mongoose.model('Book', bookSchema);    \n    ```\n3. Store as a constant:\n\n    ```JavaScript\n        const Book = mongoose.model('Book', bookSchema);\n    ```\n4. Export the model:\nThen just export the model you just created\n\n     ```JavaScript\n       const Book = mongoose.model('Book', bookSchema);\n       module.exports = { Book }\n     ```   \n\nAnd as a finished model, see how everything fits together:\n        \n```JavaScript\n        const mongoose = require(\"mongoose\");\n\n        const bookSchema = new mongoose.Schema({  \n            title: {                      \n                titleName: String,\n                type: String, \n                required: true\n            },            \n            authorName: {\n                firstName: String,\n                lastName: String,\n            }        \n            tags: [ String ],                   \n            isPublished: Boolean,      \n            date: { type: Date, default: Date.now },  \n            reviews: [{               \n                reviewer: String,\n                publication: String,\n                grade: Number,\n                date: Date\n            }]\n        });\n\n        const Book = mongoose.model(\"Book\", bookSchema);     // Create a new mongoose model of book...\n\n        module.exports = { Book };                           // and export Book (for use in server.js).\n```\n\n\u003c/dd\u003e\n\u003c/dl\u003e\n\n\u003cbr\u003e\n\n## What are Virtuals?\n\u003cdl\u003e\n\u003cdd\u003e\n\nA **virtual** allows you to manipulate properties in the schema object (which are stored in the database). In other words, it will let you take existing properties in your database to create a new property. Note that a virtual does not persist in the database, *it only exists logically* in the application and is not written anywhere in the documents collection.\n\nFor example, look at the ```authorName``` property in our bookSchema, which is an object with two properties: ```firstName``` and ```lastName```.\n```JavaScript\n    const bookSchema = new mongoose.Schema({\n        authorName: {                                        // author object with...\n            firstName: String,                               // ... first name and...\n            lastName: String,                                // ... last name properties.\n        }\n        ...\n        ...\n    });\n```\nNow suppose you want to reference the full name of the author of your books. How would you do this?\n\nYou *could* just have a property like ```fullName``` with a combination of the first and last names, but most of the time your database will not have this spcific combination. You also *could* concatenate the properties of the first and last name throughout the entire application. However, this is a bit messy. This is where *virtuals* come in. \n\nWhat a virtual will do is create a new property (that does not exist nor persist in the database) and *manipulate* those properties so that a new property is created for use in your application. In the following question, you'll see just how easy creating a new virtual property can be.\n\n### GET and SET methods for Virtuals\nMongoose has two virtual *fields*, the GET and the SET methods.\n* The **GET** method is a function that returns a virtual value, and can do complex processing or simple concatenation.\n* The **SET** method is used to split strings and perform other operations.\n\nIn the case of this study example, we'll use the GET method to concatenate the full name of our author.\n\n\u003c/dd\u003e\n\u003c/dl\u003e\n\n\u003cbr\u003e\n\n## How do you define a virtual property?\n\u003cdl\u003e\n\u003cdd\u003e\n\n### STEP 1: Declare a virtual attribute on the schema:\nTo create a virtual property, you first call the schema you wish to create a virtual property for. In this case, we want to create a virtual property for the bookSchema schema.\n```JavaScript\n    bookSchema.virtual();\n```\n\n### STEP 2: Input the new virtual property name:\nSince we want to create a full name composed of the first and last name, we'll call this virtual property \"fullName\".\n```JavaScript\n    bookSchema.virtual('fullName');\n```\n\n### STEP 3: Add the GET method and function that will return the desired result\nIn the case of this virtual property, our function will return the concatenation of the first and the last name. To do this, we need to chain the ```.get``` method a callback\nwith the desired manipulation of the properties.\n\u003e Note the use of ```.trim()``` which will eliminate excess spacing and because we are using template literals, we dont need to concatenate an empty space (i.e. X + ' ' + Y).\n```JavaScript\n    bookSchema.virtual('fullName').get( function() {\n        return `${this.authorName.firstName} ${this.authorName.lastName}`.trim();\n    });\n```\n\n### RESULT:\nSo when you call fullName, the resulting process will get the returning concatenation of the first and last name with a space in the middle.\n```\n    bookSchema.fullname          // call\n    Joe Smith                    // result\n```\n\n\u003c/dd\u003e\n\u003c/dl\u003e\n\n\u003cbr\u003e\n\n## What is an instance method and how do you implement it?\n\u003cdl\u003e\n\u003cdd\u003e\n\nAn **instance method** performs a specific action (i.e. serialize) on a specific instance of a model (i.e. a single document) rather than the entire model itself.\nInstance methods are the opposite of *static methods*, which perform some action on the *entire* model.\n\nIn the bookSchema example, the instance method we are created is ```.serialize```. Below, we have an collection of books that we have created a bookSchema for which contains \na few properties. However, to to use ```.serialize``` you need to create a custom method (i.e. ```.method```) which will will create the serialization method for every instance of \nthat model. \n\nIn the instance method below, the custom *serialize* method will be used to return an object that only exposes *some* of the fields we want from the underlying data. In other words,\nthis code will specify how ```books``` will be represented outside the application via the API.  For example, suppose we had a ```password``` property in bookSchema. This custom serialization\nmethod can make sure that the password property is left out.\n\n```JavaScript\n    bookSchema.methods.serialize = function() {\n        return {\n            title: this.title,\n            fullName: this.fullName,           // note that this is a virtual outside the bookSchema\n            tags: this.tags,                   // ... and authorName is left out because fullName is included.\n            isPublished: this.isPublished,\n            date: this.grade,\n            reviews: this.reviews\n            };\n    };\n```\n\n\u003c/dd\u003e\n\u003c/dl\u003e\n\n\u003cbr\u003e\n\n## How do Schemas and Models work with CRUD operations?\n\u003cdl\u003e\n\u003cdd\u003e\n\nMongoose uses built-in methods to interact with the database layer. [Click here for Mongoose CRUD operations](https://github.com/john-azzaro/Study-Mongoose-CRUD-Operations \"Mongoose CRUD Operations\").\n\n\u003c/dd\u003e\n\u003c/dl\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjohn-azzaro%2Fstudy-mongoose-configuration-and-data-modeling","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjohn-azzaro%2Fstudy-mongoose-configuration-and-data-modeling","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjohn-azzaro%2Fstudy-mongoose-configuration-and-data-modeling/lists"}