Mongoose
Mongoose
#mongoose
Table of Contents
About 1
Remarks 2
Versions 2
Examples 4
Installation 4
Remarks 6
Examples 6
Syntax 9
Parameters 9
Examples 9
Simple Populate 9
Nested Population 12
Syntax 14
Parameters 14
Examples 14
Examples 16
Middleware 16
Chapter 6: Mongoose Queries 18
Introduction 18
Examples 18
Examples 19
Basic Schema 19
Schema methods 19
Schema Statics 19
GeoObjects Schema 20
Examples 22
Creating a Schema 22
Credits 23
About
You can share this PDF with anyone you feel could benefit from it, downloaded the latest version
from: mongoose
It is an unofficial and free mongoose ebook created for educational purposes. All the content is
extracted from Stack Overflow Documentation, which is written by many hardworking individuals at
Stack Overflow. It is neither affiliated with Stack Overflow nor official mongoose.
The content is released under Creative Commons BY-SA, and the list of contributors to each
chapter are provided in the credits section at the end of this book. Images may be copyright of
their respective owners unless otherwise specified. All trademarks and registered trademarks are
the property of their respective company owners.
Use the content presented in this book at your own risk; it is not guaranteed to be correct nor
accurate, please send your feedback and corrections to [email protected]
https://riptutorial.com/ 1
Chapter 1: Getting started with mongoose
Remarks
Mongoose is a MongoDB object modeling tool designed to work in an asynchronous
environment.
We can easily structure our database using Schemas and Models, Automate certain things when
record is added or updated using Middlewares/Hooks and easily get the data we need by querying
our models.
Important Links
• Mongoose Quickstart
• Mongoose GitHub Repository
• Mongoose Documentation
• Mongoose Plugins
Versions
Latest release: Version 4.6.0 released on 2nd September 2016
1.0.1 2011-02-02
1.1.6 2011-03-22
1.3.0 2011-04-19
1.3.1 2011-04-27
1.3.4 2011-05-17
1.4.0 2011-06-10
1.5.0 2011-06-27
1.6.0 2011-07-07
2.0.0 2011-08-24
https://riptutorial.com/ 2
Version Release Date
2.3.4 2011-10-18
2.5.0 2012-01-26
3.0.0 2012-08-07
3.1.2 2012-09-10
3.2.0 2012-09-27
3.5.0 2012-12-10
3.5.6 2013-02-14
3.6.0 2013-03-18
3.6.5 2013-04-15
3.8.0 2013-10-31
3.8.10 2014-05-20
3.8.15 2014-08-17
4.0.0 2015-03-25
4.0.6 2015-06-21
4.1.0 2015-07-24
4.2.0 2015-10-22
4.2.10 2015-12-08
4.3.5 2016-01-09
4.4.0 2016-02-02
4.4.4 2016-02-17
4.4.8 2016-03-18
4.4.13 2016-04-21
4.4.18 2016-05-21
4.5.0 2016-06-13
4.5.5 2016-07-18
https://riptutorial.com/ 3
Version Release Date
4.5.8 2016-08-01
4.5.9 2016-08-14
4.5.10 2016-08-23
4.6.0 2016-09-02
Examples
Installation
But make sure you have also installed MongoDB for your OS or Have access to a MongoDB
database.
mongoose.Promise = global.Promise;
3. Connect to MongoDB:
mongoose.connect('mongodb://127.0.0.1:27017/database');
Note:
• By default mongoose connects to MongoDB at port 27017, Which is the default port used by
MongoDB.
• To connect to MongoDB hosted somewhere else, use the second syntax. Enter MongoDB
username, password, host, port and database name.
MongoDB port is 27017 by default; use your app name as the db name.
https://riptutorial.com/ 4
Connection with options and callback
Mongoose connect has 3 parameters, uri, options, and the callback function. To use them see
sample below.
var options = {
user: 'user1',
pass: 'pass'
}
https://riptutorial.com/ 5
Chapter 2: Mongoose Middleware
Remarks
In mongoose, Middlewares are also called as pre and post hooks.
1. Document middleware
Its supported for document functions init, validate, save and remove
2. Query middleware
Its supported for query functions count, find, findOne, findOneAndRemove, findOneAndUpdate,
insertMany and update.
1. serial
As the name suggests, Its executed in serial order i..e one after another
2. parallel
Parallel middleware offers more fine-grained flow control and the hooked method is not
executed until done is called by all parallel middleware.
Post Middleware are executed after the hooked method and all of its pre middleware have been
completed.
hooked methods are the functions supported by document middleware. init, validate, save,
remove
Examples
Middleware to hash user password before saving it
In this example, We will write a middleware that will convert the plain text password into a hashed
https://riptutorial.com/ 6
password before saving it in database.
This middleware will automatically kick in when creating new user or updating existing user details.
FILENAME : User.js
/**
* This is the middleware, It will be called before saving any record
*/
UserSchema.pre('save', function(next) {
// call your hashPassword method here which will return the hashed password.
this.password = hashPassword(this.password);
});
Now every time we save a user, This middleware will check if password is set and is modified
(this is so we dont hash users password if its not modified.)
FILENAME : App.js
// connect to MongoDB
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://127.0.0.1:27017/database');
https://riptutorial.com/ 7
let app = express();
/* ... express middlewares here .... */
/*
req.body = {
name: 'John Doe',
email: '[email protected]',
password: '!trump'
}
*/
});
https://riptutorial.com/ 8
Chapter 3: Mongoose Population
Syntax
1. Model.Query.populate(path, [select], [model], [match], [options]);
Parameters
Param Details
Examples
Simple Populate
Mongoose populate is used to show data for referenced documents from other collections.
Lets say we have a Person model that has referenced documents called Address.
Person Model
Address Model
https://riptutorial.com/ 9
To populate Address inside Person using it's ObjectId, using let's say findOne(), use the populate()
function and add the field key address as the first parameter.
Person.findOne({_id: req.params.id})
.populate('address') // <- use the populate() function
.exec(function(err, person) {
// do something.
// variable `person` contains the final populated data
});
Or
Person Doc
{
"_id":"123abc",
"fname":"John",
"mname":"Kennedy",
"lname":"Doe",
"address":"456def" // <- Address' Id
}
Address Doc
{
"_id":"456def",
"houseNum":"2",
"street":"Street 2",
"city":"City of the dead",
"state":"AB",
"country:"PH"
}
Populated Doc
{
"_id":"123abc",
"fname":"John",
"mname":"Kennedy",
"lname":"Doe",
"address":{
"_id":"456def",
"houseNum":"2",
"street":"Street 2",
"city":"City of the dead",
"state":"AB",
"country:"PH"
https://riptutorial.com/ 10
}
}
Let's say you don't want the fields houseNum and street in the address field of the final populated
doc, use the populate() as follows,
Person.findOne({_id: req.params.id})
.populate('address', '-houseNum -street') // note the `-` symbol
.exec(function(err, person) {
// do something.
// variable `person` contains the final populated data
});
Or
Populated Doc
{
"_id":"123abc",
"fname":"John",
"mname":"Kennedy",
"lname":"Doe",
"address":{
"_id":"456def",
"city":"City of the dead",
"state":"AB",
"country:"PH"
}
}
If you only want the fields houseNum and street in the address field in the final populated doc, use
the populate() function as follows in the above two methods,
Person.findOne({_id: req.params.id})
.populate('address', 'houseNum street')
.exec(function(err, person) {
// do something.
// variable `person` contains the final populated data
});
Or
https://riptutorial.com/ 11
Person.findOne({_id: req.params.id}, function(err, person) {
// do something
// variable `person` contains the final populated data
})
.populate('address', 'houseNum street');
Populated Doc
{
"_id":"123abc",
"fname":"John",
"mname":"Kennedy",
"lname":"Doe",
"address":{
"_id":"456def",
"houseNum":"2",
"street":"Street 2"
}
}
Nested Population
Lets say you have a user schema, which contains name , contactNo, address, and friends.
If you want to find a user, his friends and friends of friends, you need to do population on 2
levels i.e. nested Population.
User.find({_id : userID})
.populate({
path : 'friends',
populate : { path : 'friends'}//to find friends of friends
});
All the parameters and options of populate can be used inside nested populate too, to get the
desired result.
It is not recommended to do nested population for more than 3 levels. In case you need to do
https://riptutorial.com/ 12
nested populate for more than 3 levels, you might need to restructure your schema.
https://riptutorial.com/ 13
Chapter 4: Mongoose Population
Syntax
• Query.populate(path, [select], [model], [match], [options])
Parameters
Parameter Explanation
<Object, String> Field selection for the population query (can use '-id' to
[select]
include everything but the id field)
<Model> The model you wish to use for population.If not specified, populate will
[model]
look up the model by the name in the Schema's ref field.
Examples
A simple mongoose populate example
in Mongoose allows you to populate a reference you have in your current collection or
.populate()
document with the information from that collection. The previous may sound confusing but I think
an example will help clear up any confusion.
https://riptutorial.com/ 14
var User = mongoose.model('User', userSchema);
var Post = mongoose.model('Post', postSchema);
If we wanted to populate all of the posts for each user when we .find({}) all of the Users, we
could do the following:
User
.find({})
.populate('posts')
.exec(function(err, users) {
if(err) console.log(err);
//this will log all of the users with each of their posts
else console.log(users);
})
https://riptutorial.com/ 15
Chapter 5: mongoose pre and post
middleware (hooks)
Examples
Middleware
Middleware (also called pre and post hooks) are functions which are passed control during
execution of asynchronous functions. Middleware is specified on the schema level and is useful for
writing plugins. Mongoose 4.0 has 2 types of middleware: document middleware and query
middleware. Document middleware is supported for the following document functions.
• init
• validate
• save
• remove
Query middleware is supported for the following Model and Query functions.
• count
• find
• findOne
• findOneAndRemove
• findOneAndUpdate
• update
Both document middleware and query middleware support pre and post hooks.
Pre
Serial
Serial middleware are executed one after another, when each middleware calls next.
Parallel
https://riptutorial.com/ 16
var schema = new Schema(..);
The hooked method, in this case save, will not be executed until done is called by each
middleware.
Post middleware
post middleware are executed after the hooked method and all of its pre middleware have
completed. post middleware do not directly receive flow control, e.g. no next or done callbacks are
passed to it. post hooks are a way to register traditional event listeners for these methods.
schema.post('init', function(doc) {
console.log('%s has been initialized from the db', doc._id);
});
schema.post('validate', function(doc) {
console.log('%s has been validated (but not saved yet)', doc._id);
});
schema.post('save', function(doc) {
console.log('%s has been saved', doc._id);
});
schema.post('remove', function(doc) {
console.log('%s has been removed', doc._id);
});
https://riptutorial.com/ 17
Chapter 6: Mongoose Queries
Introduction
Mongoose is a Node.JS driver for MongoDB. It provides certain benefits over the default
MongoDB driver, such as adding types to Schemas. One difference is that some Mongoose
queries may differ from their MongoDB equivalents.
Examples
Find One Query
The findOne method will return the first entry in the database that matches the first parameter. The
parameter should be an object where the key is the field to look for and the value is the value to be
matched. This can use MongoDB query syntax, such as the dot (.) operator to search subfields.
https://riptutorial.com/ 18
Chapter 7: Mongoose Schemas
Examples
Basic Schema
Schema Types.
Schema methods
Methods can be set on Schemas to help doing things related to that schema(s), and keeping them
well organized.
userSchema.methods.normalize = function() {
this.name = this.name.toLowerCase();
};
Example usage:
Schema Statics
Schema Statics are methods that can be invoked directly by a Model (unlike Schema Methods,
which need to be invoked by an instance of a Mongoose document). You assign a Static to a
schema by adding the function to the schema's statics object.
https://riptutorial.com/ 19
return this.model.find({ name: name }, callback);
}
GeoObjects Schema
A generic schema useful to work with geo-objects like points, linestrings and polygons. Both
Mongoose and MongoDB support Geojson.
This kind of schema will be useful if you want to keep trace of your items by insertion time or
update time.
https://riptutorial.com/ 20
if(!this.created_at) {
this.created_at = now
}
next();
});
https://riptutorial.com/ 21
Chapter 8: Mongoose Schemas
Examples
Creating a Schema
//Each key in the schema is associated with schema type (ie. String, Number, Date, etc)
var gameSchema = new mongoose.Schema({
name: String,
players: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Player'
}],
host: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Player'
},
board: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Board'
},
active: {
type: Boolean,
default: true
},
state: {
type: String,
enum: ['decision', 'run', 'waiting'],
default: 'waiting'
},
numFlags: {
type: Number,
enum: [1,2,3,4]
},
isWon: {
type: Boolean,
default: false
}
});
mongoose.model('Game', gameSchema);
https://riptutorial.com/ 22
Credits
S.
Chapters Contributors
No
Mongoose
2 Delapouite, Random User
Middleware
Mongoose
3 CENT1PEDE, Chinni, Medet Tleukabiluly, Ravi Shankar
Population
https://riptutorial.com/ 23